﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.XPath;
using System.IO;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Globalization;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Threading;

namespace Helper_Ji
{
    public class Helper_Fetion
    {
        Client fetion = new Client();
        public Helper_Fetion(string mobile, string pwd)
        {
            InitFx();
            fetion.Login(mobile, pwd);
            
        }

        private void InitFx()
        {
            fetion = new Client();

            fetion.LoginSucceed += new EventHandler(fetion_LoginSucceed);
            fetion.LoginFailed += new EventHandler<LoginEventArgs>(fetion_LoginFailed);
            fetion.VerifyCodeRequired = (reason, picBuffer) =>
            {
                return this.InputVerifyCode(reason, picBuffer);
            };
            fetion.Load += new EventHandler(fetion_Load);
            fetion.MsgReceived+=new EventHandler<ConversationArgs>(fetion_MsgReceived);
            fetion.Deregistered+=new EventHandler(fetion_Deregistered);
            
            //fetion.AddBuddyRequest += new EventHandler<ConversationArgs>(fetion_AddBuddyApplication);
            //fetion.AddBuddyResult += new EventHandler<ConversationArgs>(fetion_AddBuddyResult);
            //fetion.DeleteBuddyResult += new EventHandler<ConversationArgs>(fetion_DeleteBuddyResult);

        }

        /// <summary>
        /// 提示输入验证码对话框
        /// </summary>
        /// <param name="reason"></param>
        /// <param name="picBuffer">验证码的buffer</param>
        /// <returns></returns>
        private string InputVerifyCode(string reason, byte[] picBuffer)
        {
            using (Helper_VerifyCode.VerifyCodeFrm frm = new Helper_VerifyCode.VerifyCodeFrm(reason, picBuffer))
            {
                DialogResult dr = frm.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    return frm.VerfyCode;
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        //private void fetion_DeleteBuddyResult(object sender, ConversationArgs e)
        //{
        //    if (e.Text == "200")
        //    {
        //        notify.ShowBalloonTip(100, "", "删除好友成功", ToolTipIcon.Info);
        //    }
        //}

        //private void fetion_AddBuddyResult(object sender, ConversationArgs e)
        //{
        //    string result = e.Text;
        //    if (!string.IsNullOrEmpty(result))
        //    {
        //        notify.ShowBalloonTip(100, "", string.Format("添加好友:{0}成功!", result), ToolTipIcon.Info);
        //    }
        //    else
        //    {
        //        notify.ShowBalloonTip(100, "", "添加好友失败!", ToolTipIcon.Info);
        //    }
        //}

        //private void fetion_AddBuddyApplication(object sender, ConversationArgs e)
        //{
        //    XDocument doc = XDocument.Parse(e.Text);
        //    string uri = doc.Element("events").Element("event").Element("application").Attribute("uri").Value;
        //    string desc = doc.Element("events").Element("event").Element("application").Attribute("desc").Value;
        //    string userid = doc.Element("events").Element("event").Element("application").Attribute("user-id").Value;

        //    fetion.SendToSelf(uri + "添加你为好友");
        //    fetion.AgreeAddBuddy(new SipUri(uri), userid);

        //    RobotCore.SendEMail("HaozesFx Robot Message", uri.ToString() + " 添加你的机器人为好友,机器人已自动添加他为好友");
        //}



        void fetion_LoginFailed(object sender, LoginEventArgs e)
        {
            
        }

        void fetion_LoginSucceed(object sender, EventArgs e)
        {
            
        }

        void fetion_Deregistered(object sender, EventArgs e)
        {
            LogoutFx();
          //  if (sc != null)
               // sc.Post(AlterLoginBtn, true);
        }
        private void LogoutFx()
        {
            fetion.Exit();
            fetion.LoginSucceed -= new EventHandler(fetion_LoginSucceed);
            fetion.LoginFailed -= new EventHandler<LoginEventArgs>(fetion_LoginFailed);
            fetion.Load -= new EventHandler(fetion_Load);
            fetion.MsgReceived -= new EventHandler<ConversationArgs>(fetion_MsgReceived);
            fetion.Deregistered -= new EventHandler(fetion_Deregistered);
        }

        private SynchronizationContext sc;
        void fetion_MsgReceived(object sender, ConversationArgs e)
        {
            if (sender != null)
            {
                Conversation conv = (Conversation)sender;
                if (e.MsgType == IMType.Text || e.MsgType == IMType.SMS)
                {
                   
                    SMSMessageEventArgs sms = new SMSMessageEventArgs();
                    sms.Message= Helper_HTML.NoHTML(e.Text);
                    OnResivingEvent(sms);
                    //MessageBox.Show(e.Text); 
                    //hook robot here
                    //RobotConvAnalyzer analyzer = new RobotConvAnalyzer(conv);
                    //analyzer.ParseMsg(e.Text);
                }

            }
        }

        public event EventHandler<SMSMessageEventArgs> OnResiving;
        public virtual void OnResivingEvent(SMSMessageEventArgs message)
        {
            var handler = OnResiving;
            if (handler != null)
                handler(this, message);
        
        }
        public class SMSMessageEventArgs : EventArgs
        {
            public string Message { get; set; }
        }



        private void fetion_Load(object sender, EventArgs e)
        {
          
            fetion.SetPresence(PresenceStatus.Active);
        }
    }

    public class Client
    {
        private User user;
        private LoginMgr loginMgr;
        private ConversationMgr convMgr;
        private bool isAlive = true;

        //获取单个用户的信息
        private Conversation convGetContactInfo;

        //被添加好友会话
        private Conversation convHandleContactRequest;
        private Conversation convAddBuddy;
        private Conversation convDeleteBuddy;

        private Conversation convSetPresence;

        public event EventHandler LoginSucceed;
        public event EventHandler<LoginEventArgs> LoginFailed;

        /// <summary>
        /// 验证码处理函数.必须赋值 
        /// </summary>
        public Func<string, byte[], string> VerifyCodeRequired { get; set; }

        //好友列表完全加载成功
        public event EventHandler Load;
        public event EventHandler<ConversationArgs> MsgReceived;
      //  public event EventHandler<FxErrArgs> Errored;

        //从其他客户端登陆
        public event EventHandler Deregistered;

        //别人添加自己为好友事件
        public event EventHandler<ConversationArgs> AddBuddyRequest;

        //添加别人为好友事件
        public event EventHandler<ConversationArgs> AddBuddyResult;
        public event EventHandler<ConversationArgs> DeleteBuddyResult;

        public Client()
        {
           // ErrManager.Erroring += new EventHandler<FxErrArgs>(this.OnErrored);
        }

        public void Login(string mobile, string pwd)
        {
            this.user = new User(long.Parse(mobile), pwd);
            this.loginMgr = new LoginMgr(this.user);
            this.loginMgr.LoginSucceed += new EventHandler<LoginEventArgs>(this.LoginMgr_LoginSuccess);
          //  this.loginMgr.LoginFailed += new EventHandler<LoginEventArgs>(this.OnLoginFailed);
            this.loginMgr.VerifyCodeRequired = this.VerifyCodeRequired;
            this.loginMgr.Login();
            this.isAlive = true;
        }

        public void Exit()
        {
            if (this.isAlive == false)
                return;
            this.user.Conncetion.Close();
           // ErrManager.Erroring -= new EventHandler<FxErrArgs>(this.OnErrored);
           // this.loginMgr.LoginSucceed -= new EventHandler<LoginEventArgs>(this.LoginMgr_LoginSuccess);
           // this.loginMgr.LoginFailed -= new EventHandler<LoginEventArgs>(this.OnLoginFailed);
            this.isAlive = false;
        }

        private void LoginMgr_LoginSuccess(object sender, LoginEventArgs e)
        {
           // LogUtil.Log.Debug("完全登陆成功,初始化好友列表成功!");

            System.Threading.Thread.Sleep(100);

            this.convMgr = loginMgr.ConversationManager;
            this.convMgr.MsgReceived += new EventHandler<ConversationArgs>(this.MsgReceived);
            this.convMgr.PresenceNotify += new EventHandler<ConversationArgs>(convMgr_PresenceNotify);
            this.convMgr.Deregistered += new EventHandler(this.Deregistered);
         //   this.convMgr.AddBuddyRequest += new EventHandler<ConversationArgs>(this.AddBuddyRequest);
            //this.convMgr.UpdateBuddyRequest += new EventHandler<ConversationArgs>(this.ConvMgr_UpdateBuddyRequest);
            this.convMgr.SyncUserInfo += new EventHandler<ConversationArgs>(convMgr_SyncUserInfo);

            this.SubPresence();
            if (this.LoginSucceed != null)
            {
                this.LoginSucceed(this, null);
            }
            if (this.Load != null)
            {
                this.Load(this, null);
            }
            this.user.Conncetion.StartKeepLive();
        }


        private void SubPresence()
        {
            SipMessage subPresPkt = PacketFactory.SubPresence();
            this.user.Conncetion.Send(subPresPkt);
        }

        void convMgr_PresenceNotify(object sender, ConversationArgs e)
        {
            this.user.ContactsManager.PresenceNotify(e.Text);
        }

        private void convMgr_SyncUserInfo(object sender, ConversationArgs e)
        {
            XDocument doc = XDocument.Parse(e.Text);

            //忽略了其他消息,如用户等级等
            if (doc.Element("events")
                                  .Element("event")
                                      .Element("user-info")
                                          .Element("contact-list") == null)
                return;

            var buddylist = doc.Element("events")
                                 .Element("event")
                                     .Element("user-info")
                                         .Element("contact-list")
                                             .Element("buddies")
                                                 .Elements("buddy");
            if (buddylist != null)
            {
                foreach (var buddy in buddylist)
                {
                    var action = buddy.Attribute("action").Value;
                    var userid = buddy.Attribute("user-id").Value;
                    switch (action.ToLower())
                    {
                        case "remove":
                            this.user.ContactsManager.Delete(userid);
                            break;
                        case "add":
                            var localName = buddy.Attribute("local-name").Value;
                            var uri = buddy.Attribute("uri").Value;
                            this.user.ContactsManager.Add(new Contact(new SipUri(uri), localName, ContactType.Buddy));
                            break;
                        case "update":
                            var c = this.user.ContactsManager.GetContact(userid);
                            if (c != null)
                            {
                                this.GetContactInfo(c.Uri, c.UserId);
                            }
                            break;
                        default:
                            break;
                    }

                }
            }
        }

        //protected virtual void OnLoginFailed(object sender, LoginEventArgs e)
        //{
        //    if (this.LoginFailed != null)
        //    {
        //        this.Log.Error(e.ToString());
        //        this.LoginFailed(this, e);
        //    }
        //}

        //protected virtual void OnErrored(object sender, Helper_Ji.SipResponseReceivedEventArgs.FxErrArgs e)
        //{
        //    this.Log.Error(e.ToString());
        //    if (this.Errored != null)
        //    {
        //        this.Errored(this, e);
        //    }
        //}

        public bool IsALive
        {
            get { return this.isAlive; }
            set { this.isAlive = value; }
        }

        //public log4net.ILog Log
        //{
        //    get { return LogUtil.Log; }
        //    set { LogUtil.Init(value); }
        //}

        public User CurrentUser
        {
            get { return this.user; }
        }

        public void Send(Conversation conv, string content)
        {
            if (this.convMgr.HasConversation(conv))
            {
                conv.SendMsg(content);
            }
            else
            {
                this.SendSMS(conv.From, content);
            }
        }

        public void SendMsg(SipUri uri, string content)
        {
            this.convMgr.SendMsg(uri, content);
        }

        public void SendMsg(SipMessage rcvPacket, string msgContent)
        {
            this.convMgr.SendMsg(rcvPacket, msgContent);
        }

        public void SendSMS(string mobile, string content)
        {
            this.SendSMS(new SipUri(mobile), content, false);
        }

        /// <summary>
        /// Sends the SMS.
        /// </summary>
        /// <param name="mobile">The mobile.</param>
        /// <param name="content">The content.</param>
        /// <param name="isCatMsg">是否是长短信</param>
        public void SendSMS(string mobile, string content, bool isCatMsg)
        {
            this.SendSMS(new SipUri(mobile), content, isCatMsg);
        }

        public void SendSMS(SipUri uri, string content)
        {
            this.SendSMS(uri, content, false);
        }

        /// <summary>
        /// Sends the SMS.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="content">The content.</param>
        /// <param name="isCatMsg">是否是长短信</param>
        public void SendSMS(SipUri uri, string content, bool isCatMsg)
        {
            this.convMgr.SendSMS(uri, content, isCatMsg);
        }

        public void SendToSelf(string content)
        {
            this.convMgr.SendSMS(this.CurrentUser.Uri, content, true);
        }

        /// <summary>
        /// 添加好友
        /// </summary>
        /// <param name="uri">sipuri</param>
        /// <param name="desc">description,为空时显示用户昵称</param>
        public void AddBuddy(SipUri uri, string desc)
        {
            if (this.isAlive == false)
                return;
            SipMessage packet = PacketFactory.AddBuddy(uri, desc);
            this.convAddBuddy = this.convMgr.Create(packet, true);
            this.convAddBuddy.MsgRcv += new EventHandler<ConversationArgs>(this.ConvAddBuddy_MsgRcv);
        }

        private void ConvAddBuddy_MsgRcv(object sender, ConversationArgs e)
        {
            SipMessage sipMsg = e.RawPacket;
            SipResponse rsp = sipMsg as SipResponse;
            string result = string.Empty;
            if (rsp != null)
            {
             //   this.Log.Debug(string.Format("addbuddy result:{0}", e.RawPacket));
                if (rsp.StatusCode == 200)
                {
                    XDocument doc = XDocument.Parse(e.Text);
                    if (doc.Element("results").Element("contacts") != null)
                    {
                        var buddies = doc.Element("results").Element("contacts").Element("buddies").Elements("buddy");
                        foreach (var buddy in buddies)
                        {
                            string localname = buddy.Attribute("local-name").Value;
                            string userid = buddy.Attribute("user-id").Value;
                            string uri = buddy.Attribute("uri").Value;
                            result = uri;
                        }
                    }
                }
                if (this.AddBuddyResult != null)
                {
                    ConversationArgs resultArg = new ConversationArgs(IMType.AddBuddyResult, rsp);
                    resultArg.Text = result;
                    this.AddBuddyResult(this, resultArg);
                    this.convAddBuddy.MsgRcv -= new EventHandler<ConversationArgs>(this.ConvAddBuddy_MsgRcv);
                }
            }
        }

        public void GetContactInfo(SipUri uri, string userid)
        {
            SipMessage packet = PacketFactory.GetContactsInfo(uri, userid);
            this.convGetContactInfo = this.convMgr.Create(packet, true);
            this.convGetContactInfo.MsgRcv += new EventHandler<ConversationArgs>(this.ConvGetContactInfo_MsgRcv);
        }

        private void ConvGetContactInfo_MsgRcv(object sender, ConversationArgs e)
        {
            SipResponse rsp = e.RawPacket as SipResponse;
            if (rsp.StatusCode != 200)
            {
                //this.Log.Info("未能获取该好友详细信息");
                return;
            }

            XDocument doc = XDocument.Parse(e.Text);
            if (doc.Element("results").Elements("contact").Count() > 0)
            {
                foreach (var c in doc.Element("results").Elements("contact"))
                {
                    SipUri uri = new SipUri(c.Attribute("uri").Value);
                    string userid = c.Attribute("user-id").Value;
                    string mobile = c.Attribute("mobile-no") != null ? c.Attribute("mobile-no").Value : string.Empty;
                    string name = c.Attribute("name").Value;
                    string nickname = c.Attribute("nickname").Value;
                    string impresa = c.Attribute("impresa").Value;
                    Contact contact = new Contact(uri, userid, string.Empty, nickname, ContactType.Buddy);
                    if (!string.IsNullOrEmpty(mobile))
                        contact.MobileNo = long.Parse(mobile);
                    contact.Impresa = impresa;
                    this.user.ContactsManager.Add(contact);
                }
                this.convGetContactInfo.MsgRcv -= new EventHandler<ConversationArgs>(this.ConvGetContactInfo_MsgRcv);
            }

        }

        // 同意对方添加自己为好友
        public void AgreeAddBuddy(SipUri uri, string userid)
        {
            SipMessage agreePacket = PacketFactory.HandleContactRequest(userid);
            this.convHandleContactRequest = this.convMgr.Create(agreePacket, true);
            this.convHandleContactRequest.MsgRcv += new EventHandler<ConversationArgs>(this.ConvHandleContactRequest_MsgRcv);
            this.user.ContactsManager.Add(new Contact(uri, string.Empty, ContactType.Buddy));
        }

        private void ConvHandleContactRequest_MsgRcv(object sender, ConversationArgs e)
        {
            XDocument doc = XDocument.Parse(e.Text);
            if (doc.Element("results").Element("contacts") != null)
            {
                var buddies = doc.Element("results").Element("contacts").Element("buddies").Elements("buddy");
                foreach (var buddy in buddies)
                {
                    string localname = buddy.Attribute("local-name").Value;
                    string userid = buddy.Attribute("user-id").Value;
                    Contact c = this.user.ContactsManager.GetContact(userid);
                    if (c != null)
                    {
                        c.LocalName = localname;
                        this.user.ContactsManager.Update(c);
                    }
                }
                this.convHandleContactRequest.MsgRcv -= new EventHandler<ConversationArgs>(this.ConvHandleContactRequest_MsgRcv);
            }
        }

        public void DeleteBuddy(SipUri buddyUri)
        {
            Contact c = this.user.ContactsManager.Find(buddyUri);
            if (c != null && !string.IsNullOrEmpty(c.UserId))
            {
                this.DeleteBuddy(c.UserId);
            }
        }

        public void DeleteBuddy(string userid)
        {
            var deletePacket = PacketFactory.DeleteBuddy(userid);
            this.convDeleteBuddy = this.convMgr.Create(deletePacket, true);
            this.convDeleteBuddy.MsgRcv += new EventHandler<ConversationArgs>(this.ConvDeleteBuddy_MsgRcv);
        }

        private void ConvDeleteBuddy_MsgRcv(object sender, ConversationArgs e)
        {
            SipResponse rsp = e.RawPacket as SipResponse;
            if (rsp != null)
            {
                XmlDocument document = new XmlDocument();
                document.LoadXml(rsp.Body);
                XmlNode node = document.SelectSingleNode("results/contacts/buddies/buddy");
                if (node != null)
                {
                    string uri =Helper_Data. XmlHelper.ReadXmlAttributeString(node, "uri");
                    if (!string.IsNullOrEmpty(uri))
                    {
                        this.user.ContactsManager.Delete(new SipUri(uri));
                    }
                }
                ConversationArgs resultArg = new ConversationArgs(IMType.DeleteBuddyResult, rsp);
                resultArg.Text = rsp.StatusCode.ToString();
                this.DeleteBuddyResult(this, resultArg);
                this.convDeleteBuddy.MsgRcv -= new EventHandler<ConversationArgs>(this.ConvDeleteBuddy_MsgRcv);
            }
        }

        public void SetPresence(PresenceStatus statu)
        {
            SipMessage sipPacket = PacketFactory.SetPresence(statu);
            this.convSetPresence = this.convMgr.Create(sipPacket, true);
            this.convSetPresence.MsgRcv += new EventHandler<ConversationArgs>(convSetPresence_MsgRcv);
        }

        void convSetPresence_MsgRcv(object sender, ConversationArgs e)
        {
            SipMessage sipPacket = PacketFactory.PGSetPresence();
            this.convMgr.SendRawPacket(sipPacket);
            this.convMgr.Remove(int.Parse(e.RawPacket.CallID.Value));
        }
    }


    public class User
    {
        //好友列表更新

        private SipConnection sipConnection = new SipConnection();
        private PortInfo portInfo = new PortInfo();
        private SipSysConfig sysConfig = new SipSysConfig();
        private SipUri uri = null;
        private string nickname = string.Empty;
        private string impresa = string.Empty;
        private long mobileNo = long.MinValue;
        private string userid = string.Empty;
        private string pwd = string.Empty;
        private string hashPwd = string.Empty;
        private string name = string.Empty;
        private int gender = -1;
        private string personalEmail = string.Empty;
        private ContactMgr contactMgr = null;

        public IList<Contact> Contacts
        {
            get { return this.contactMgr.Contacts; }
        }

        public string NickName
        {
            get { return this.nickname; }
        }

        public long MobileNo
        {
            get { return this.mobileNo; }
        }

        public string UserId
        {
            get { return this.userid; }
        }

        public string Name
        {
            get { return this.name; }
        }

        public string Password
        {
            get { return this.pwd; }
        }

        public string HashedPassword
        {
            get { return this.hashPwd; }
        }

        public int Gender
        {
            get { return this.gender; }
        }

        public string PersonalEmail
        {
            get { return this.personalEmail; }
        }

        public User()
        {
        }

        public User(long mobileNo, string password)
        {
            this.mobileNo = mobileNo;
            this.pwd = password;
            this.hashPwd = HashPasswod.DoHashPassword(this.pwd);
            this.contactMgr = new ContactMgr();
        }

        public void CreatePortInfo(string[] list)
        {
            this.portInfo = LoginHelper.LoadPortInfo(list);
            this.uri = this.portInfo.HostUri;
            this.userid = this.portInfo.UserId;
        }

        public void CreateSipSysConfig(string xml)
        {
            this.sysConfig = LoginHelper.LoadSipSysConfig(xml);
        }

        public void CreatePersonalInfo(string xml)
        {
            TextReader reader = new StringReader(xml);
            XPathDocument doc = new XPathDocument(reader);
            XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator();
            XPathNodeIterator iter = nav.Select("/results/user-info/personal");
            iter.MoveNext();
            this.nickname = iter.Current.GetAttribute("nickname", string.Empty);
            this.impresa = iter.Current.GetAttribute("impresa", string.Empty);
            this.name = iter.Current.GetAttribute("name", string.Empty);
            this.mobileNo = long.Parse(iter.Current.GetAttribute("mobile-no", string.Empty));
            this.gender = int.Parse(iter.Current.GetAttribute("gender", string.Empty));
        }

        public Contact FindContact(SipUri uri)
        {
            return this.contactMgr.Find(uri);
        }

        public PortInfo Port
        {
            get { return this.portInfo; }
        }

        public SipSysConfig SysConfig
        {
            get { return this.sysConfig; }
        }

        public SipUri Uri
        {
            get { return this.uri; }
            set { this.uri = value; }
        }

        public SipConnection Conncetion
        {
            get { return this.sipConnection; }
            set { this.sipConnection = value; }
        }

        public ContactMgr ContactsManager
        {
            get { return this.contactMgr; }
        }
    }

    public class PortInfo
    {
        private string ssic = string.Empty;
        private SipUri hostUri = null;
        private string domain = string.Empty;
        private string credential = string.Empty;
        private string userid = string.Empty;

        public PortInfo()
        {
        }

        public void Load(string[] list)
        {
            this.ssic = list[0].Replace("ssic=", string.Empty);
            TextReader reader = new StringReader(list[1]);
            XPathDocument doc = new XPathDocument(reader);
            XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator();
            XPathNodeIterator iter = nav.Select("//@uri");
            iter.MoveNext();
            this.hostUri = new SipUri(iter.Current.Value);

            iter = nav.Select("//@user-id");
            iter.MoveNext();
            this.userid = iter.Current.Value.Trim();

            iter = nav.Select("//results/user/credentials/credential[1]");
            iter.MoveNext();
            this.domain = iter.Current.GetAttribute("domain", string.Empty);

            iter = nav.Select("//results/user/credentials/credential[1]");
            iter.MoveNext();
            this.credential = iter.Current.GetAttribute("c", string.Empty);
        }

        public string Ssic
        {
            get { return this.ssic; }
        }

        public SipUri HostUri
        {
            get { return this.hostUri; }
        }

        public string UserId
        {
            get { return this.userid; }
        }

        public string Domain
        {
            get { return this.domain; }
        }

        public string Credential
        {
            get { return this.credential; }
        }
    }

    public class SipUri
    {
        private Uri uri = null;

        public Uri Uri
        {
            get { return this.uri; }
        }

        private long num = long.MinValue;

        /// <summary>
        /// 飞信号或手机号
        /// </summary>
        public long Sid
        {
            get { return this.num; }
        }

        private void Init(Uri uri)
        {
            this.uri = uri;
            if (this.uri.Scheme.ToLower() == "sip")
            {
                string[] arr = uri.LocalPath.Split('@');
                this.num = long.Parse(arr[0]);
            }
            else if (uri.Scheme.ToLower() == "tel")
            {
                this.num = long.Parse(uri.LocalPath);
            }
            else
            {
                throw new ArgumentException("不是合法的SipUri格式");
            }
        }

        public SipUri()
        {
        }

        public SipUri(string rawUri)
        {
            bool ok = Uri.TryCreate(rawUri.Trim(), UriKind.Absolute, out this.uri);
            if (ok)
            {
                this.Init(this.uri);
            }
        }

        public SipUri(Uri uri)
        {
            this.Init(uri);
        }

        public string Raw
        {
            get { return this.uri.ToString(); }
        }

        public override string ToString()
        {
            return this.uri.ToString();
        }

        public override int GetHashCode()
        {
            return this.Raw.GetHashCode();
        }

        public override bool Equals(Object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            SipUri p = (SipUri)obj;
            return this.Raw == p.Raw;
        }
    }

    public class SipConnection : BaseSipConnection
    {

        protected virtual void KeepConnectionBusy(object state)
        {
            SipMessage hpPacket = PacketFactory.KeepConnectionBusy();
            this.Send(hpPacket);
        }

        protected virtual void KeepLive(object state)
        {
            SipMessage hpPacket = PacketFactory.GetKeepAlivePacket();
            this.Send(hpPacket);
        }

        public override void StartKeepLive()
        {
            int period = 3000 * 60;
            int dueTime = 10000;

            //心跳包一分钟调一次
            this.timerKeepLive = new System.Threading.Timer(new System.Threading.TimerCallback(this.KeepLive), this.socket, dueTime, period);

            //int kpbusyPeriod=1000*30;
            // this.timerKeepConnectionBusy = new Timer(new TimerCallback(this.KeepConnectionBusy),this.socket,0,kpbusyPeriod);
        }

    }

    public abstract class BaseSipConnection
    {
        protected Socket socket = null;
        protected string remoteIp = string.Empty;
        protected string remotePort = string.Empty;

        protected volatile int callID = 1;
        protected volatile int cseq = 1;
        protected volatile bool isClosed = false;
        protected System.Threading.Timer timerKeepLive;
        protected System.Threading.Timer timerKeepConnectionBusy;

        protected byte[] recvBuffers = new byte[0x1000];
        protected SipParser parser = new SipParser();

        public event EventHandler<ConversationArgs> MessageReceived;

        public BaseSipConnection()
            : this(null)
        {
        }

        public BaseSipConnection(Socket socket)
            : this(socket, 1)
        {
        }

        public BaseSipConnection(Socket socket, int callID)
        {
            this.callID = callID;
            this.socket = socket;
            this.parser.RequestReceived += new EventHandler<SipRequestReceivedEventArgs>(this.Parser_RequestReceived);
            this.parser.ResponseReceived += new EventHandler<SipResponseReceivedEventArgs>(this.Parser_ResponseReceived);
            this.parser.MessageParsingFailed += new EventHandler(this.Parser_MessageParsingFailed);
        }

        public virtual Socket SipSocket
        {
            get { return this.socket; }
            set { this.socket = value; }
        }

        public virtual void Connect(string ip, string port)
        {
            try
            {
                this.remoteIp = ip;
                this.remotePort = port;
                this.socket = Helper_TCP.CreateSocket(ip, port);
            }
            catch (Exception ex)
            {
                // ErrManager.RaiseError(new FxErrArgs(ErrLevel.Fatal, ex));
            }
        }

        public virtual System.Net.EndPoint LocalEndPoint
        {
            get { return this.socket.LocalEndPoint; }
        }

        public virtual string RemoteIP
        {
            get { return this.remoteIp; }
        }

        public virtual string RemotePort
        {
            get { return this.remotePort; }
        }

        public virtual int NextCallID()
        {
            return ++this.callID;
        }

        public virtual int CallID
        {
            get { return this.callID; }
            set { this.callID = value; }
        }

        public virtual int Cseq
        {
            get { return this.cseq; }
            set { this.cseq = value; }
        }

        public virtual int NextCseq()
        {
            return ++this.cseq;
        }

        public virtual void StartListen()
        {
            this.ListenAsync(this.socket);
        }

        public abstract void StartKeepLive();

        protected virtual void ListenAsync(object o)
        {
            if (this.isClosed)
                return;
            try
            {
                Socket state = o as Socket;
                state.BeginReceive(this.recvBuffers, 0, this.recvBuffers.Length, SocketFlags.None, new AsyncCallback(this.ReceiveData), state);
            }
            catch (Exception ex)
            {
                // LogUtil.Log.Error("ListenAsync异常:" + ex.ToString());
                return;
            }
        }

        protected virtual void ReceiveData(IAsyncResult iar)
        {
            int recv = 0;
            Socket remote = null;
            try
            {
                remote = (Socket)iar.AsyncState;
                recv = remote.EndReceive(iar);
                byte[] data = new byte[recv];
                Buffer.BlockCopy(this.recvBuffers, 0, data, 0, data.Length);
                if (data.Length < 2)
                    return;
                // DebugWriter.WriteLine(">>>>>>>receive data:" + Encoding.UTF8.GetString(data));
                this.parser.Parse(data, 0, data.Length);
            }
            catch (SocketException ex)
            {
                string err = "ReceiveData异常:" + ex.ToString();
                if (ex.ErrorCode != (int)SocketError.OperationAborted)
                {//上个线程退出
                    return;
                }
                // LogUtil.Log.Warn(err);
                return;
            }
            this.ListenAsync(remote);
        }

        public virtual void Send(SipMessage packet)
        {
            // DebugWriter.WriteSendPacket(packet);
            try
            {
                Helper_TCP.AsyncSend(this.socket, packet, this.SendCallback);
            }
            catch (SocketException ex)
            {
                //   LogUtil.Log.Error(ex);
                //  ErrManager.RaiseError(new FxErrArgs(ErrLevel.Fatal, ex));
            }
        }

        public virtual void SendCallback(IAsyncResult ar)
        {
            Socket socket = null;
            try
            {
                socket = ar as Socket;
            }
            catch (Exception exception)
            {
                string errInfo = string.Format("AysncSend:异步发送数据发生错误！:remoteip:{0},port:{1}", this.remoteIp, this.socket.LocalEndPoint.ToString());
                //    LogUtil.Log.Error(exception.ToString());
                //   ErrManager.RaiseError(new FxErrArgs(ErrLevel.Fatal, exception));
            }
        }

        public virtual void Close()
        {
            this.isClosed = true;

            this.parser.RequestReceived -= new EventHandler<SipRequestReceivedEventArgs>(this.Parser_RequestReceived);
            this.parser.ResponseReceived -= new EventHandler<SipResponseReceivedEventArgs>(this.Parser_ResponseReceived);
            this.parser.MessageParsingFailed -= new EventHandler(this.Parser_MessageParsingFailed);
            if (this.timerKeepLive != null)
            {
                this.timerKeepLive.Dispose();
            }
            if (this.socket != null)
            {
                this.socket.Shutdown(SocketShutdown.Both);
                this.socket.Close();
            }
        }

        protected virtual void Parser_MessageParsingFailed(object sender, EventArgs e)
        {
            //   LogUtil.Log.Error("数据解析失败");
        }

        protected virtual void Parser_ResponseReceived(object sender, SipResponseReceivedEventArgs e)
        {
            if (this.MessageReceived != null)
            {
                this.MessageReceived(this, new ConversationArgs(e.Response));
            }
        }

        protected virtual void Parser_RequestReceived(object sender, SipRequestReceivedEventArgs e)
        {
            if (this.MessageReceived != null)
            {
                this.MessageReceived(this, new ConversationArgs(e.Request));
            }
        }
    }

    public class SipParser
    {
        private LineReader reader = new LineReader();
        private SipRequestReceivedEventArgs requestEventArgs = new SipRequestReceivedEventArgs();
        private SipResponseReceivedEventArgs responseEventArgs = new SipResponseReceivedEventArgs();
        private MemoryStream stream = new MemoryStream(0x800);
        public const int MaxMessageLength = 0x20000;

        public event EventHandler MessageParsingFailed;
        public event EventHandler<SipRequestReceivedEventArgs> RequestReceived;
        public event EventHandler<SipResponseReceivedEventArgs> ResponseReceived;

        public SipParser()
        {
            this.reader.Bind(this.stream);
        }

        private void MoveData(long pos)
        {
            if (pos == 0L)
            {
                this.stream.Position = this.stream.Length;
            }
            else if ((pos < 0L) || (pos >= this.stream.Length))
            {
                this.stream.Position = 0L;
                this.stream.SetLength(0L);
            }
            else
            {
                MemoryStream stream = new MemoryStream(0x800);
                stream.Write(this.stream.GetBuffer(), (int)pos, (int)(this.stream.Length - pos));
                this.stream = stream;
                this.reader.Bind(this.stream);
            }
        }

        private bool CheckLine(string line)
        {
            if (line == null)
            {
                return false;
            }
            byte[] buffer = this.stream.GetBuffer();
            return ((buffer[(int)((IntPtr)(this.stream.Position - 1L))] == 10) && (buffer[(int)((IntPtr)(this.stream.Position - 2L))] == 13));
        }

        private void TryToParse()
        {
            string line = this.reader.ReadLine();
            if (this.CheckLine(line))
            {
                bool flag;
                if (line.IndexOf(Protocol.Version) == 0)
                {
                    flag = this.ParseResponse(line);
                }
                else
                {
                    flag = this.ParseRequest(line);
                }
                long pos = 0L;
                while (flag)
                {
                    pos = this.stream.Position;
                    line = this.reader.ReadLine();
                    if (!this.CheckLine(line))
                    {
                        break;
                    }
                    if (line.IndexOf(Protocol.Version) == 0)
                    {
                        flag = this.ParseResponse(line);
                    }
                    else
                    {
                        flag = this.ParseRequest(line);
                    }
                }
                this.MoveData(pos);
            }
        }

        public void Parse(byte[] buffer, int pos, int len)
        {
            this.stream.Write(buffer, pos, len);
            if (this.stream.Length > 8L)
            {
                this.stream.Seek(0L, SeekOrigin.Begin);
                this.TryToParse();
            }
            if ((this.stream.Length >= MaxMessageLength) && (this.MessageParsingFailed != null))
            {
                this.MessageParsingFailed(this, EventArgs.Empty);
            }
        }

        private SipHeadField ParseHeadField(string name, string value)
        {
            name = name.ToUpper();
            if (SipKey.HeadFieldList.ContainsKey(name))
            {
                return new SipHeadField(name, value);
            }
            return null;
        }

        private bool ParseBody(SipMessage msg)
        {
            SipHeadField lengthField = msg.ContentLength;
            if ((lengthField != null) && (Int32.Parse(lengthField.Value) >= 1))
            {
                int len = Int32.Parse(lengthField.Value);
                if ((this.stream.Length - this.stream.Position) < len)
                {
                    return false;
                }
                msg.BodyBuffer = new byte[len];
                this.stream.Read(msg.BodyBuffer, 0, len);
            }
            return true;
        }

        private bool ParseHeaders(SipMessage msg)
        {
            for (string str = this.reader.ReadLine(); this.CheckLine(str); str = this.reader.ReadLine())
            {
                if (str.Length < 1)
                {//空白行解析开始Body部分
                    return this.ParseBody(msg);
                }
                int index = str.IndexOf(": ");
                if (index < 1)
                {
                    return false;
                }
                string name = str.Substring(0, index);
                SipHeadField header = this.ParseHeadField(name, str.Substring(index + 2));
                if (header != null)
                {
                    msg.HeadFields.Add(header);
                }
            }
            return false;
        }

        private bool CheckResponse(SipResponse rsp)
        {
            if (((rsp.CallID != null) && (rsp.CSeq != null)) && ((rsp.ContentLength == null) || ((int.Parse(rsp.ContentLength.Value) >= 0) && (int.Parse(rsp.ContentLength.Value) < MaxMessageLength))))
            {
                return true;
            }
            if (this.MessageParsingFailed != null)
            {
                this.MessageParsingFailed(this, EventArgs.Empty);
            }
            return false;
        }

        private bool ParseResponse(string line)
        {
            int blankIndex1 = line.IndexOf(" ");
            int blankIndex2 = line.IndexOf(" ", (int)(blankIndex1 + 1));
            if ((blankIndex1 < 1) || (blankIndex2 < 1))
            {
                if (this.MessageParsingFailed != null)
                {
                    this.MessageParsingFailed(this, EventArgs.Empty);
                }
                return false;
            }
            try
            {
                SipResponse msg = new SipResponse(int.Parse(line.Substring(blankIndex1, blankIndex2 - blankIndex1)), line.Substring(blankIndex2 + 1));
                if (this.ParseHeaders(msg))
                {
                    if (!this.CheckResponse(msg))
                    {
                        return false;
                    }
                    this.responseEventArgs.Response = msg;
                    if (this.ResponseReceived != null)
                    {
                        this.ResponseReceived(this, this.responseEventArgs);
                    }
                    return true;
                }
                return false;
            }
            catch (Exception exception)
            {
                //Trace.WriteLine(exception.ToString());
                return false;
            }
        }

        private bool CheckRequest(SipRequest req)
        {
            SipHeadField callId = req.CallID;
            SipHeadField cSeq = req.CSeq;

            string method = Helper_Sip.SipHelper.GetCSeqMethod(cSeq);
            if (((callId != null) && (cSeq != null)) && (method == req.Method))
            {
                SipHeadField contentLength = req.ContentLength;
                if (contentLength == null)
                {
                    return true;
                }
                int len = int.Parse(contentLength.Value);
                if ((len >= 0) && (len < MaxMessageLength))
                {
                    return true;
                }
            }
            if (this.MessageParsingFailed != null)
            {
                this.MessageParsingFailed(this, EventArgs.Empty);
            }
            return false;
        }

        private bool ParseRequest(string line)
        {
            if (line.Length >= 1)
            {
                string[] strArray = line.Split(new char[] { ' ' });
                if (((strArray.Length != 3) || (strArray[2] != Protocol.Version)) || !SipKey.MethodNameList.ContainsKey(strArray[0]))
                {
                    if (this.MessageParsingFailed != null)
                    {
                        this.MessageParsingFailed(this, EventArgs.Empty);
                    }
                    return false;
                }
                SipRequest msg = new SipRequest(strArray[0], strArray[1]);
                if (!this.ParseHeaders(msg))
                {
                    return false;
                }
                if (!this.CheckRequest(msg))
                {
                    return false;
                }
                this.requestEventArgs.Request = msg;
                if (this.RequestReceived != null)
                {
                    this.RequestReceived(this, this.requestEventArgs);
                }
            }
            return true;
        }

        public void Clear()
        {
            this.stream = new MemoryStream(0x800);
            this.reader.Bind(this.stream);
        }

        public string GetUnderlyContent()
        {
            if ((this.stream != null) && (this.stream.Length > 0L))
            {
                return Encoding.UTF8.GetString(this.stream.GetBuffer(), 0, (int)this.stream.Length);
            }
            return string.Empty;
        }
    }

    public class SipRequest : SipMessage
    {
        private string method = string.Empty;
        private string uri = string.Empty;

        public SipRequest()
        {
        }

        public SipRequest(string method, string uri)
        {
            this.method = method;
            this.uri = uri;
        }

        protected override string GetFirstLine()
        {
            return string.Format("{0} {1} " + Protocol.Version, this.method, this.uri);
        }

        public string Method
        {
            get
            {
                return this.method;
            }

            set
            {
                this.method = value;
            }
        }

        public string Uri
        {
            get
            {
                return this.uri;
            }

            set
            {
                this.uri = (value == null) ? string.Empty : value.Trim();
            }
        }
    }

    public abstract class SipMessage
    {
        private string body = string.Empty;
        private byte[] bodyBuffer;
        private IList<SipHeadField> headFielders = new List<SipHeadField>();

        public SipMessage()
        {
        }

        public void AddFielder(SipHeadField fielder)
        {
            this.headFielders.Add(fielder);
        }

        protected abstract string GetFirstLine();

        public virtual byte[] ToBinary()
        {
            string s = this.ToString();
            return Encoding.UTF8.GetBytes(s);
        }

        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine(this.GetFirstLine());
            foreach (var field in this.headFielders)
            {
                if (field.Name != "L" && !string.IsNullOrEmpty(field.Value))
                {
                    builder.AppendLine(field.ToString());
                }
            }
            string body = this.Body;
            if (this.body.Trim().Length > 0)
            {
                SipHeadField lengthField = new SipHeadField(Helper_Sip.SipHeadFieldName.ContentLength, Encoding.UTF8.GetByteCount(body).ToString());
                builder.AppendLine(lengthField.ToString());
                builder.AppendLine(Environment.NewLine + body);
            }
            else
            {
                builder.AppendLine(Environment.NewLine + Environment.NewLine);
            }
            return builder.ToString();
        }

        public string Body
        {
            get
            {
                if (string.IsNullOrEmpty(this.body))
                {
                    if (this.bodyBuffer == null)
                    {
                        return string.Empty;
                    }
                    this.body = Encoding.UTF8.GetString(this.bodyBuffer);
                }
                return this.body;
            }
            set
            {
                this.body = (value == null) ? string.Empty : value;
            }
        }

        public byte[] BodyBuffer
        {
            get
            {
                return this.bodyBuffer;
            }
            internal set
            {
                this.bodyBuffer = value;
                this.body = null;
            }
        }

        public IList<SipHeadField> HeadFields
        {
            get { return this.headFielders; }
        }

        public SipHeadField this[string name]
        {
            get
            {
                foreach (var item in this.headFielders)
                {
                    if (name == item.Name)
                        return item;
                }
                return null;
            }
        }

        public SipHeadField Authorization
        {
            get { return this["A"]; }
        }

        public SipHeadField CallID
        {
            get { return this["I"]; }
        }

        public SipHeadField Contact
        {
            get { return this["M"]; }
        }

        public SipHeadField ContentEncoding
        {
            get { return this["E"]; }
        }

        public SipHeadField ContentLength
        {
            get { return this["L"]; }
        }

        public SipHeadField ContentType
        {
            get { return this["C"]; }
        }

        public SipHeadField CSeq
        {
            get { return this["Q"]; }
        }

        public SipHeadField Date
        {
            get { return this["D"]; }
        }

        public SipHeadField EndPoints
        {
            get { return this["EP"]; }
        }

        public SipHeadField Event
        {
            get { return this["N"]; }
        }

        public SipHeadField Expires
        {
            get { return this["X"]; }
        }

        public SipHeadField From
        {
            get { return this["F"]; }
        }

        public SipHeadField MessageID
        {
            get { return this["XI"]; }
        }

        public SipHeadField ReferredBy
        {
            get { return this["RB"]; }
        }

        public SipHeadField ReferTo
        {
            get { return this["RT"]; }
        }

        public SipHeadField Require
        {
            get { return this["RQ"]; }
        }

        public SipHeadField RosterManager
        {
            get { return this["RM"]; }
        }

        public SipHeadField Source
        {
            get { return this["SO"]; }
        }

        public SipHeadField Supported
        {
            get { return this["K"]; }
        }

        public SipHeadField To
        {
            get { return this["T"]; }
        }

        public SipHeadField Unsupported
        {
            get { return this["UK"]; }
        }

        public SipHeadField WWWAuthenticate
        {
            get { return this["W"]; }
        }
    }

    public class SipHeadField
    {
        private string name = string.Empty;
        private string value = string.Empty;
        public SipHeadField()
        {
        }

        public SipHeadField(string name, string value)
        {
            this.name = name;
            this.value = value;
        }

        public SipHeadField(string name)
            : this(name, string.Empty)
        {
        }

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public string Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public override string ToString()
        {
            return string.Format("{0}: {1}", this.name, this.value);
        }

    }

    public class SipSysConfig
    {
        private string sipcProxy = string.Empty;
        private string sipcSslProxy = string.Empty;
        private string ssiAppSignIn = string.Empty;
        private string ssiAppSignOut = string.Empty;
        private string portal = string.Empty;
        private string serverVersion = string.Empty;
        #region unusedKey
        //sub-service
        //apply-sub-service
        //crbt-portal
        //email-adapter
        //get-general-info
        //get-pic-code
        //get-svc-order-status
        //get-system-status
        //get-sipUri
        //group-category
        //group-website
        //matching-portal
        #endregion

        public SipSysConfig()
        {
        }

        public void Load(string data)
        {
            TextReader reader = new StringReader(data);
            XPathDocument doc = new XPathDocument(reader);
            XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator();
            XPathNodeIterator iter = nav.Select("/config/servers/sipc-proxy");
            iter.MoveNext();
            this.sipcProxy = iter.Current.Value;

            iter = nav.Select("/config/servers/sipc-ssl-proxy");
            iter.MoveNext();
            this.sipcSslProxy = iter.Current.Value;

            //iter = nav.Select("/config/servers/ssi-app-sign-in");
            iter = nav.Select("/config/servers/ssi-app-sign-in-v2");
            iter.MoveNext();
            this.ssiAppSignIn = iter.Current.Value;

            iter = nav.Select("/config/servers/ssi-app-sign-out");
            iter.MoveNext();
            this.ssiAppSignOut = iter.Current.Value;

            iter = nav.Select("/config/servers/portal");
            iter.MoveNext();
            this.portal = iter.Current.Value;

            iter = nav.Select("/config/servers/server-version");
            iter.MoveNext();
            this.serverVersion = iter.Current.Value;
        }

        public string SipcProxy
        {
            get { return this.sipcProxy; }
        }

        public string SipcSslProxy
        {
            get { return this.sipcSslProxy; }
        }

        public string SsiAppSignIn
        {
            get { return this.ssiAppSignIn; }
        }

        public string SsiAppSignOut
        {
            get { return this.ssiAppSignOut; }
        }

        public string Portal
        {
            get { return this.portal; }
        }

        public string ServerVersion
        {
            get { return this.serverVersion; }
        }
    }

    public class ContactMgr
    {
        private int buddyCount = 0;
        private List<Contact> contactList = new List<Contact>();
        public event EventHandler<ContactsChangedArg> ContactsChanged;

        public IList<Contact> Contacts
        {
            get { return this.contactList; }
        }

        public void InitContactList(string xml)
        {
            Helper_Data.XmlParser xmlParser = new Helper_Data.XmlParser(xml);
            DataTable dtBuddies = xmlParser.GetDataTable("//results/user-info/contact-list/buddies");
            DataTable dtMobileBuddies = xmlParser.GetDataTable("//results/user-info/contact-list/chat-friends");
            DataTable dtBlockedBuddies = xmlParser.GetDataTable("//results/user-info/contact-list/blacklist");

            xmlParser.Dispose();
            if (dtBuddies != null)
            {
                foreach (DataRow row in dtBuddies.Rows)
                {
                    Contact c = new Contact(
                        new SipUri(row["u"].ToString()),
                        row["i"].ToString(),
                        row["n"].ToString(),
                        string.Empty,
                        ContactType.Buddy);
                    this.contactList.Add(c);
                    this.buddyCount++;
                }
            }

            if (dtMobileBuddies != null)
            {
                foreach (DataRow row in dtMobileBuddies.Rows)
                {
                    Contact c = new Contact(
                        new SipUri(row["u"].ToString()),
                        row["i"].ToString(),
                        string.Empty,
                        string.Empty,
                        ContactType.MobileBuddy);
                    this.contactList.Add(c);
                }
            }
            if (dtBlockedBuddies != null)
            {
                foreach (DataRow row in dtBlockedBuddies.Rows)
                {
                    Contact c = new Contact(
                        new SipUri(row["u"].ToString()),
                        row["i"].ToString(),
                        row["n"].ToString(),
                        string.Empty,
                        ContactType.BlockedBuddy);
                    this.contactList.Add(c);
                }
            }

            this.contactList.Sort(delegate(Contact c1, Contact c2) { return c1.DisplayName.CompareTo(c2.DisplayName); });
        }

        public void PresenceNotify(string xml)
        {
            string id = string.Empty;
            string nickName = string.Empty;
            string impresa = string.Empty;
            string mobileNo = string.Empty;
            string name = string.Empty;
            TextReader reader = new StringReader(xml);
            XPathDocument doc = new XPathDocument(reader);
            XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator();
            XPathNodeIterator iter = nav.Select("//events/event/contacts/c");
            while (iter.MoveNext())
            {
                id = iter.Current.GetAttribute("id", string.Empty);
                if (string.IsNullOrEmpty(id))
                    continue;
                Contact contact = null;
                foreach (var c in this.contactList)
                {
                    if (c.UserId == id)
                    {
                        contact = c;
                        break;
                    }
                }
                if (contact != null)
                {
                    this.buddyCount--;
                    XPathNodeIterator pIter = iter.Current.SelectChildren("p", string.Empty);
                    pIter.MoveNext();
                    nickName = pIter.Current.GetAttribute("n", string.Empty);
                    contact.NickName = nickName;
                    impresa = pIter.Current.GetAttribute("i", string.Empty);
                    contact.Impresa = impresa;
                    mobileNo = pIter.Current.GetAttribute("m", string.Empty);
                    long mobile = long.MinValue;
                    long.TryParse(mobileNo, out mobile);
                    contact.MobileNo = mobile;
                }
            }
        }

        public IList<Contact> GetContactByType(IList<Contact> list, ContactType contactType)
        {
            IList<Contact> group = new List<Contact>();
            if (list.Count > 0)
            {
                foreach (Contact c in list)
                {
                    if (c.ContactTypeName == contactType)
                        group.Add(c);
                }
            }
            return group;
        }

        public Contact Find(SipUri uri)
        {
            var contact = (from c in this.contactList
                           where string.Equals(c.Uri.ToString(), uri.ToString(), StringComparison.CurrentCultureIgnoreCase) == true
                           select c).SingleOrDefault();
            return contact;
        }

        public Contact Find(string id)
        {
            var contact = (from c in this.contactList
                           where string.Equals(c.Uri.Sid.ToString(), id, StringComparison.CurrentCultureIgnoreCase) == true
                           select c).SingleOrDefault();
            return contact;
        }

        public Contact GetContact(string userid)
        {
            var contact = (from c in this.contactList
                           where string.Equals(c.UserId, userid, StringComparison.CurrentCultureIgnoreCase) == true
                           select c).SingleOrDefault();
            return contact;
        }

        public void Add(Contact c)
        {
            if (this.Find(c.Uri) == null)
            {
                this.contactList.Add(c);
                if (this.ContactsChanged != null)
                {
                    this.ContactsChanged(this, new ContactsChangedArg(ContactsChangedType.Add));
                }
            }
        }

        public void Delete(Contact c)
        {
            if (c != null && this.Find(c.Uri) != null)
            {
                this.contactList.Remove(c);
            }
            if (this.ContactsChanged != null)
            {
                this.ContactsChanged(this, new ContactsChangedArg(ContactsChangedType.Delete));
            }
        }

        public void Delete(SipUri buddyUri)
        {
            Contact c = this.Find(buddyUri);
            this.Delete(c);
        }

        public void Delete(string userid)
        {
            var contact = (from c in contactList
                           where c.UserId.Equals(userid, StringComparison.CurrentCultureIgnoreCase)
                           select c).SingleOrDefault();
            if (contact != null)
                this.Delete(contact);
        }

        public void Update(Contact c)
        {
            if (this.ContactsChanged != null)
            {
                this.ContactsChanged(this, new ContactsChangedArg(ContactsChangedType.Update));
            }
        }
    }

    public enum ContactType
    {
        Buddy,
        MobileBuddy,
        BlockedBuddy
    }

    public class Contact
    {
        private SipUri uri = null;
        private string userid = string.Empty;
        private string localName = string.Empty;
        private string nickName = string.Empty;
        private string impresa = string.Empty;
        private long mobileNo = long.MinValue;
        private ContactType contactType;

        public Contact()
        {
        }

        public Contact(SipUri uri)
            : this(uri, string.Empty, ContactType.Buddy)
        {
        }

        public Contact(SipUri uri, string userid, string localName, string nickName, ContactType contactType)
        {
            this.uri = uri;
            this.localName = localName;
            this.nickName = nickName;
            this.contactType = contactType;
            this.userid = userid;
        }

        public Contact(SipUri uri, string localName, string nickName, ContactType contactType)
        {
            this.uri = uri;
            this.localName = localName;
            this.nickName = nickName;
            this.contactType = contactType;
            this.userid = string.Empty;
        }

        public Contact(SipUri uri, string localName, ContactType contactType)
            : this(uri, string.Empty, localName, string.Empty, contactType)
        {
        }

        public long MobileNo
        {
            get { return this.mobileNo; }
            set { this.mobileNo = value; }
        }

        public SipUri Uri
        {
            get { return this.uri; }
            set { this.uri = value; }
        }

        public string LocalName
        {
            get { return this.localName; }
            set { this.localName = value; }
        }

        public string NickName
        {
            get { return this.nickName; }
            set { this.nickName = value; }
        }

        public string Impresa
        {
            get { return this.impresa; }
            set { this.impresa = value; }
        }

        public string DisplayName
        {
            get
            {
                if (!string.IsNullOrEmpty(this.localName))
                    return this.localName;
                else if (!string.IsNullOrEmpty(this.nickName))
                    return this.nickName;
                else
                    return this.uri.Sid.ToString();
            }
        }

        public ContactType ContactTypeName
        {
            get { return this.contactType; }
        }

        public string UserId
        {
            get { return this.userid; }
            set { this.userid = value; }
        }
    }

    public class HashPasswod
    {
        public static string DoHashPassword(byte[] password)
        {
            byte[] bytes = BitConverter.GetBytes(Environment.TickCount);
            return DoHashPassword(password, bytes);
        }

        public static string DoHashPassword(byte[] password, byte[] b0)
        {
            using (SHA1 sha = SHA1.Create())
            {
                byte[] src = sha.ComputeHash(password);
                for (int i = 0; i < password.Length; i++)
                {
                    password[i] = 0;
                }
                byte[] dst = new byte[b0.Length + src.Length];
                System.Buffer.BlockCopy(b0, 0, dst, 0, b0.Length);
                System.Buffer.BlockCopy(src, 0, dst, b0.Length, src.Length);
                byte[] buffer3 = sha.ComputeHash(dst);
                byte[] buffer4 = new byte[b0.Length + buffer3.Length];
                System.Buffer.BlockCopy(b0, 0, buffer4, 0, b0.Length);
                System.Buffer.BlockCopy(buffer3, 0, buffer4, b0.Length, buffer3.Length);
                return ComputeAuthResponse.BinaryToHex(buffer4);
            }
        }

        public static string DoHashPassword(string pwd)
        {
            char[] chArray = pwd.ToCharArray();

            byte[] bytes = Encoding.UTF8.GetBytes(chArray);
            return HashPasswod.DoHashPassword(bytes);
        }

        public class ComputeAuthResponse
        {
            // Fields
            private string _cnonce;
            private string _domain;
            private string _nonce;
            private string _password;
            private static Random _random;
            private string _sid;
            private bool _usingSHA1;

            // Methods
            public ComputeAuthResponse(string sid, string password, string domain, string nonce, bool usingSHA1)
            {
                this._sid = sid;
                this._password = password;
                this._domain = domain;
                this._nonce = nonce;
                this._usingSHA1 = usingSHA1;
                int seed = DateTime.Now.DayOfYear * 0xf4240;
                seed += DateTime.Now.Hour * 0x2710;
                seed += DateTime.Now.Minute * 100;
                seed += DateTime.Now.Second;
                _random = new Random(seed);
            }

            public static string BinaryToHex(byte[] binary)
            {
                StringBuilder builder = new StringBuilder();
                foreach (byte num in binary)
                {
                    if (num > 15)
                    {
                        builder.AppendFormat("{0:X}", num);
                    }
                    else
                    {
                        builder.AppendFormat("0{0:X}", num);
                    }
                }
                return builder.ToString();
            }

            private string ComputeH1(byte[] key)
            {
                string s = string.Format(":{0}:{1}", this._nonce, this._cnonce);
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                byte[] array = new byte[key.Length + bytes.Length];
                key.CopyTo(array, 0);
                Array.Copy(bytes, 0, array, key.Length, bytes.Length);
                return MD5ToHex(array);
            }

            private string ComputeH2()
            {
                string s = string.Format("REGISTER:{0}", this._sid);
                return MD5ToHex(Encoding.UTF8.GetBytes(s));
            }

            private byte[] ComputeKey()
            {
                if (this._usingSHA1)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(this._sid + ":" + this._domain + ":");
                    byte[] src = HexToBinary(this._password.Substring(8));
                    byte[] dst = new byte[bytes.Length + src.Length];
                    Buffer.BlockCopy(bytes, 0, dst, 0, bytes.Length);
                    Buffer.BlockCopy(src, 0, dst, bytes.Length, src.Length);
                    return Helper_Security.GetSha1(dst);
                }
                string s = string.Format("{0}:{1}:{2}", this._sid, this._domain, this._password);
                return MD5(Encoding.UTF8.GetBytes(s));
            }

            public string ComputeResponse()
            {
                byte[] key = this.ComputeKey();
                string str = this.ComputeH1(key);
                string str2 = this.ComputeH2();
                return this.ComputeResponse(str, str2);
            }

            private string ComputeResponse(string h1, string h2)
            {
                string s = string.Format("{0}:{1}:{2}", h1, this._nonce, h2);
                return MD5ToHex(Encoding.UTF8.GetBytes(s));
            }

            private static string GenNonce()
            {
                int num = 0;
                int num2 = 0;
                int num3 = 0;
                int num4 = 0;
                lock (_random)
                {
                    num = _random.Next();
                    num2 = _random.Next();
                    num3 = _random.Next();
                    num4 = _random.Next();
                }
                if ((num >> 0x18) < 0x10)
                {
                    num += 0x10000000;
                }
                if ((num2 >> 0x18) < 0x10)
                {
                    num2 += 0x10000000;
                }
                if ((num3 >> 0x18) < 0x10)
                {
                    num3 += 0x10000000;
                }
                if ((num4 >> 0x18) < 0x10)
                {
                    num4 += 0x10000000;
                }
                return string.Format("{0:X}{1:X}{2:X}{3:X}", new object[] { num, num2, num3, num4 });
            }

            public string GetCNonce()
            {
                this._cnonce = GenNonce();
                return this._cnonce;
            }

            public static byte[] HexToBinary(string hex)
            {
                if ((hex == null) || (hex.Length < 1))
                {
                    return new byte[0];
                }
                int num = hex.Length / 2;
                byte[] buffer = new byte[num];
                num *= 2;
                for (int i = 0; i < num; i++)
                {
                    int num3 = int.Parse(hex.Substring(i, 2), NumberStyles.HexNumber);
                    buffer[i / 2] = (byte)num3;
                    i++;
                }
                return buffer;
            }

            private static byte[] MD5(byte[] data)
            {
                return System.Security.Cryptography.MD5.Create().ComputeHash(data);
            }

            private static string MD5ToHex(byte[] data)
            {
                data = MD5(data);
                return BinaryToHex(data);
            }


            public static string ComputeNewResponse(string userid, string plainpwd, string key, string nonce)
            {
                string aesKey = "568AC8CA87A03B388903BFD6C7836B6A00FB32755CD68EEEE9CEDFD234DC8451";
                byte[] aesKeyArr = Helper_String.HexStringToByteArray(aesKey);

                byte[] passwordArr = Helper_String.HexStringToByteArray(Helper_Security.EncryptV4(int.Parse(userid), plainpwd));
                byte[] nonceArr = Encoding.UTF8.GetBytes(nonce);
                // byte[] data = password+Encoding.UTF8.GetBytes(nonce)+hex2byteArray(AESKey)
                byte[] dst = new byte[passwordArr.Length + nonceArr.Length + aesKeyArr.Length];
                System.Array.Copy(nonceArr, 0, dst, 0, nonceArr.Length);
                System.Array.Copy(passwordArr, 0, dst, nonceArr.Length, passwordArr.Length);
                System.Array.Copy(aesKeyArr, 0, dst, nonceArr.Length + passwordArr.Length, aesKeyArr.Length);

                RSAParameters rsaKey = Helper_Security.ParsePublicKey(key);
                byte[] encryptArr = Helper_Security.RSAEncrypt(dst, rsaKey, false);
                string response = Helper_String.Hex2Str(encryptArr);
                return response;
            }
        }
    }

    public static class LoginHelper
    {
        public static PortInfo LoadPortInfo(string[] list)
        {
            PortInfo port = new PortInfo();
            port.Load(list);
            return port;
        }

        public static SipSysConfig LoadSipSysConfig(string xml)
        {
            SipSysConfig config = new SipSysConfig();
            config.Load(xml);
            return config;
        }
    }

    public class ContactsChangedArg : EventArgs
    {
        private ContactsChangedType changedType;
        public ContactsChangedArg(ContactsChangedType changedType)
        {
            this.changedType = changedType;
        }
        public ContactsChangedType ChangedType
        {
            get { return this.changedType; }
        }
    }

    public enum ContactsChangedType
    {
        LoadCompleted,
        Add,
        Update,
        Delete
    }

    public class LineReader
    {
        private static char[] newLine = new char[] { '\r', '\n' };
        private MemoryStream stream;

        public void Bind(MemoryStream stream)
        {
            this.stream = stream;
        }

        public string ReadLine()
        {
            long position = this.stream.Position;
            while (this.stream.Position < this.stream.Length)
            {
                if (((this.stream.ReadByte() == 13) && (this.stream.Position < this.stream.Length)) && (this.stream.ReadByte() == 10))
                {
                    break;
                }
            }
            long num2 = this.stream.Position;
            if (num2 <= position)
            {
                return null;
            }
            string str = Encoding.UTF8.GetString(this.stream.GetBuffer(), (int)position, (int)(num2 - position));
            if (str == null)
            {
                return null;
            }
            return str.TrimEnd(newLine);
        }
    }

    public class SipRequestReceivedEventArgs : EventArgs
    {
        private SipRequest request;

        public SipRequest Request
        {
            get { return this.request; }
            set { this.request = value; }
        }

        public SipRequestReceivedEventArgs()
        {
        }

        public SipRequestReceivedEventArgs(SipRequest request)
        {
            this.request = request;
        }
    }

    public enum IMType
    {
        Text,
        SMS,
        AddBuddyRequest,
        AddBuddyResult,
        DeleteBuddyResult,
        Internal
    }

    public class ConversationArgs : EventArgs
    {
        private IMType imType;
        private string text;
        private SipMessage sipMessage;
        private SipMessage originMessage;

        public ConversationArgs(SipMessage sipMessage)
            : this(IMType.Internal, sipMessage, null)
        {
        }

        public ConversationArgs(IMType imType, SipMessage sipMessage)
            : this(imType, sipMessage, null)
        {
        }

        public ConversationArgs(IMType imType, SipMessage sipMessage, SipMessage originMessage)
        {
            this.imType = imType;
            this.sipMessage = sipMessage;
            this.text = sipMessage.Body;
            this.originMessage = originMessage;
        }

        public IMType MsgType
        {
            get { return this.imType; }
        }

        /// <summary>
        /// 会话结果,默认为SipMessage Body部分
        /// </summary>
        public string Text
        {
            get { return this.text; }
            set { this.text = value; }
        }

        public SipMessage RawPacket
        {
            get { return this.sipMessage; }
        }

        public SipMessage OriginPacket
        {
            get { return this.originMessage; }
        }
    }

    public class SipResponse : SipMessage
    {
        private int statusCode;
        private string reasonPhrase = string.Empty;

        public SipResponse()
        {
        }

        public SipResponse(int statusCode, string reasonPhrase)
        {
            this.statusCode = statusCode;
            this.reasonPhrase = reasonPhrase;
        }

        protected override string GetFirstLine()
        {
            return string.Format(Protocol.Version + " {0} {1}", this.statusCode, this.reasonPhrase);
        }

        public int StatusCode
        {
            get { return this.statusCode; }
            set { this.statusCode = value; }
        }

        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }
            set { this.reasonPhrase = value; }
        }

        public class Protocol
        {
            public static string Version = "SIP-C/4.0";
        }
    }

    public class SipResponseReceivedEventArgs : EventArgs
    {
        private SipResponse response;

        public SipResponse Response
        {
            get { return this.response; }
            set { this.response = value; }
        }

        public SipResponseReceivedEventArgs()
        {
        }

        public SipResponseReceivedEventArgs(SipResponse response)
        {
            this.response = response;
        }

        public class ErrManager
        {
            public static event EventHandler<FxErrArgs> Erroring;

            public static void RaiseError(FxErrArgs e)
            {
                if (Erroring != null)
                {
                    Erroring(null, e);
                }
            }
        }

        public enum ErrLevel
        {
            Normal,
            Critical,
            Fatal
        }

        public class FxErrArgs : EventArgs
        {
            private ErrLevel level = ErrLevel.Normal;
            private Exception ex = null;
            private string summary = string.Empty;

            public FxErrArgs(Exception ex)
                : this(ErrLevel.Normal, ex)
            {
            }

            public FxErrArgs(ErrLevel level, Exception ex)
                : this(level, string.Empty, ex)
            {
            }

            public FxErrArgs(ErrLevel level, string summary, Exception ex)
            {
                this.level = level;
                this.summary = summary;
                this.ex = ex;
            }

            public string Summary
            {
                get { return this.summary; }
                set { this.summary = value; }
            }

            public ErrLevel Level
            {
                get { return this.level; }
                set { this.level = value; }
            }

            public Exception InnerException
            {
                get { return this.ex; }
                set { this.ex = value; }
            }

            public override string ToString()
            {
                string str = string.Format("ErrLevel:{0} {1} Detail:{1}", this.level, this.summary, this.ex.ToString());
                return str;
            }
        }
    }

    public class SipKey
    {
        private static IDictionary<string, string> sipMethodNames = new Dictionary<string, string>();
        private static IDictionary<string, string> sipHeaderFields = new Dictionary<string, string>();
        static SipKey()
        {
            //method
            sipMethodNames.Add(Helper_Sip.SipMethodName.Ack, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Benotify, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Bye, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Cancel, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Info, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Invite, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Message, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Negotiate, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Notify, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Options, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Refer, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Register, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Service, string.Empty);
            sipMethodNames.Add(Helper_Sip.SipMethodName.Subscribe, string.Empty);
            //header
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Authorization, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.CallID, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Contact, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.ContentEncoding, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.ContentLength, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.ContentType, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.CSeq, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Date, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.EndPoints, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Event, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Expires, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.From, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.MessageID, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.ReferredBy, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.ReferTo, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Require, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.RosterManager, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Source, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Supported, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.To, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.Unsupported, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.WWWAuthenticate, string.Empty);
            sipHeaderFields.Add(Helper_Sip.SipHeadFieldName.AL, string.Empty);
        }

        public static IDictionary<string, string> HeadFieldList
        {
            get
            {
                return sipHeaderFields;
            }
        }

        public static IDictionary<string, string> MethodNameList
        {
            get
            {
                return sipMethodNames;
            }
        }


    }

    public class PacketFactory
    {
        private static long keepLiveCSeq = 2;
        public static User Ower;
        public static readonly string DEFAULT_URI = "fetion.com.cn";

        public static SipMessage RegSipcStep1(string cn)
        {
            string msgContent = Environment.NewLine;
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, "1");
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Register);
            SipHeadField hCN = new SipHeadField("CN", cn);
            SipHeadField hCL = new SipHeadField("CL", "type = \"pc\", version = \"4.0.2510\"");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hCN);
            req.HeadFields.Add(hCL);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage RegSipcStep2(string response)
        {
            string msgContent = "<args><device accept-language=\"default\" machine-code=\"1F2E883F250398DEE59C33DD607A6B4C\" /><caps value=\"3FF\" /><events value=\"7F\" /><user-info mobile-no=\"" + Ower.MobileNo.ToString() + "\" user-id=\"" + Ower.UserId + "\"><personal version=\"0\" attributes=\"v4default;alv2-version;alv2-warn\" /><custom-config version=\"0\" /><contact-list version=\"0\" buddy-attributes=\"v4default\" /></user-info><credentials domains=\"fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn\" /><presence><basic value=\"400\" desc=\"\" /><extendeds /></presence></args>";
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, "1");
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "2 " + Helper_Sip.SipMethodName.Register);
            SipHeadField hAuth = new SipHeadField(Helper_Sip.SipHeadFieldName.Authorization, string.Format("Digest algorithm=\"SHA1-sess-v4\",response=\"{0}\"", response));

            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hAuth);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage RegSipcStep2(string response, string verifyAlgorithm, string type, string picResponse, string chid)
        {
            string msgContent = "<args><device accept-language=\"default\" machine-code=\"1F2E883F250398DEE59C33DD607A6B4C\" /><caps value=\"3FF\" /><events value=\"7F\" /><user-info mobile-no=\"" + Ower.MobileNo.ToString() + "\" user-id=\"" + Ower.UserId + "\"><personal version=\"0\" attributes=\"v4default;alv2-version;alv2-warn\" /><custom-config version=\"0\" /><contact-list version=\"0\" buddy-attributes=\"v4default\" /></user-info><credentials domains=\"fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn\" /><presence><basic value=\"400\" desc=\"\" /><extendeds /></presence></args>";
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, "1");
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "2 " + Helper_Sip.SipMethodName.Register);
            SipHeadField hAuth = new SipHeadField(Helper_Sip.SipHeadFieldName.Authorization, string.Format("Digest algorithm=\"SHA1-sess-v4\",response=\"{0}\"", response));
            SipHeadField hAuthExt = new SipHeadField(Helper_Sip.SipHeadFieldName.Authorization, string.Format("Verify algorithm=\"{0}\",type=\"{1}\",response=\"{2}\",chid=\"{3}\"", verifyAlgorithm, type, picResponse, chid));

            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hAuth);
            req.HeadFields.Add(hAuthExt);
            req.Body = msgContent;
            return req;
        }


        public static SipMessage GetContactsInfo(SipUri buddyUri, string userid)
        {
            //string msgContent = string.Format("<args><contacts attributes=\"mobile-no;nickname\" extended-attributes=\"score-level\"><contact uri=\"{0}\" /></contacts></args>", buddyUri.ToString());
            string msgContent = string.Format("<args><contact uri=\"{0}\" user-id=\"{1}\" version=\"0\" /></args>", buddyUri, userid);
            return GetContactsInfo(msgContent);
        }

        private static SipMessage GetContactsInfo(string msgContent)
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "GetContactInfoV4");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        /// <summary>
        /// in chat connection,callid not increase,cseq increase
        /// </summary>
        /// <param name="callid"></param>
        /// <param name="cseq"></param>
        /// <returns></returns>
        public static SipMessage KeepConnectionBusy(string callid, string cseq)
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Options, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, callid);
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, cseq + " O");
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "KeepConnectionBusy");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            return req;
        }

        /// <summary>
        /// in main sipconnection. callid increase,cseq not increase
        /// </summary>
        /// <returns></returns>
        public static SipMessage KeepConnectionBusy()
        {
            return KeepConnectionBusy(Ower.Conncetion.NextCallID().ToString(), "1");
        }

        // public static SipMessage GetKeepAlivePacket()
        public static SipMessage GetKeepAlivePacket()
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, "1");
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, NextKeepLiveCSeq());
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "KeepAlive");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = "<args><credentials domains=\"fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn;pos.fetion.com.cn\" /></args>";
            return req;
        }

        public static SipMessage GetGroupList()
        {
            /*
                S fetion.com.cn SIP-C/4.0
                F: 616325003
                I: 2 
                Q: 1 S
                N: PGGetGroupList
                L: 27

                <args><group-list /></args>
             */
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 S");
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "PGGetGroupList");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = "<args><group-list /></args>";
            return req;
        }

        public static SipMessage SubPresence()
        {
            /*
             * SUB fetion.com.cn SIP-C/4.0
                F: 616325003
                I: 3 
                Q: 1 SUB
                N: PresenceV4
                L: 112

                <args><subscription self="v4default;mail-count;impresa;sms-online-status" buddy="v4default" version="" /></args>
             */
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Subscribe, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Subscribe);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "PresenceV4");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = "<args><subscription self=\"v4default;mail-count;impresa;sms-online-status\" buddy=\"v4default\" version=\"\" /></args>";
            return req;
        }

        public static SipMessage SMSPacket(SipUri sipUri, string msgContent)
        {
            return SMSPacket(sipUri, msgContent, false);
        }

        /// <summary>
        /// SMS packet.
        /// </summary>
        /// <param name="sipUri">The sipURI.</param>
        /// <param name="msgContent">Content of the Msg.</param>
        /// <param name="isCatMsg">是否是长短信</param>
        /// <returns></returns>
        public static SipMessage SMSPacket(SipUri sipUri, string msgContent, bool isCatMsg)
        {
            string eventName = (isCatMsg == true ? "SendCatSMS" : "SendSMS");

            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Message, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Message);
            SipHeadField hTo = new SipHeadField(Helper_Sip.SipHeadFieldName.To, sipUri.ToString());
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, eventName);
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hTo);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage ReplyMsgPacket(SipMessage packet, string msgContent)
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Message, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, packet.CallID.Value);
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, packet.CSeq.Value);
            SipHeadField hTo = new SipHeadField(Helper_Sip.SipHeadFieldName.To, packet.To.Value);
            SipHeadField hContentType = new SipHeadField(Helper_Sip.SipHeadFieldName.ContentType, "text/html-fragment");
            SipHeadField hSupported = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "SaveHistory");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hTo);
            req.HeadFields.Add(hContentType);
            req.HeadFields.Add(hSupported);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage ReplyMsgPacket(Conversation conv, string msgContent)
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Message, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, conv.CallID.ToString());
            //SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, conv.CSeq);
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, conv.Connection.NextCseq().ToString() + " M");

            SipHeadField hTo = new SipHeadField(Helper_Sip.SipHeadFieldName.To, conv.From.ToString());
            SipHeadField hContentType = new SipHeadField(Helper_Sip.SipHeadFieldName.ContentType, "text/html-fragment");
            SipHeadField hSupported = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "SaveHistory");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hTo);
            req.HeadFields.Add(hContentType);
            req.HeadFields.Add(hSupported);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage LeaveMsgPacket(SipUri sipUri, string msgContent)
        {
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Message, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "2 M");
            SipHeadField hTo = new SipHeadField(Helper_Sip.SipHeadFieldName.To, sipUri.ToString());
            SipHeadField hContentType = new SipHeadField(Helper_Sip.SipHeadFieldName.ContentType, "text/plain");
            SipHeadField hSupported = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "SaveHistory");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hTo);
            req.HeadFields.Add(hContentType);
            req.HeadFields.Add(hSupported);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage RSPInvitePacket(SipMessage packet)
        {
            System.Net.EndPoint localPoint = Ower.Conncetion.LocalEndPoint;
            string port = localPoint.ToString().Split(':')[1];

            StringBuilder sb = new StringBuilder();
            sb.AppendLine("v=0");
            sb.AppendLine("o=-0 0 IN " + localPoint.ToString());
            sb.AppendLine("s=session");
            sb.AppendLine("c=IN IP4 " + localPoint.ToString());
            sb.AppendLine("t=0 0");
            sb.AppendLine(string.Format("m=message {0} sip {1}", port, Ower.Uri.Sid));
            SipResponse response = CreateDefaultResponse(packet);
            response.Body = sb.ToString();
            return response;
        }

        public static SipMessage RegToChatServer(string callid, string ticksAuth)
        {
            string msgContent = Environment.NewLine;
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Register, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, callid);
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Register);
            SipHeadField hAuth = new SipHeadField(Helper_Sip.SipHeadFieldName.Authorization, "TICKS auth=\"" + ticksAuth + "\"");
            SipHeadField hContentType1 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "text/html-fragment");
            SipHeadField hContentType2 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "multiparty");
            SipHeadField hContentType3 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "nudge");
            SipHeadField hContentType4 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "share-background");
            SipHeadField hContentType5 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "fetion-show");
            SipHeadField hContentType6 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "ExModulesApp");
            SipHeadField hContentType7 = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, "FileTransferV4");

            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hAuth);
            req.HeadFields.Add(hContentType1);
            req.HeadFields.Add(hContentType2);
            req.HeadFields.Add(hContentType3);
            req.HeadFields.Add(hContentType4);
            req.HeadFields.Add(hContentType5);
            req.HeadFields.Add(hContentType6);
            req.HeadFields.Add(hContentType7);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage RSPReceiveMsgPacket(SipMessage packet)
        {
            return CreateDefaultResponse(packet);
        }

        public static SipMessage RSPBye(SipMessage packet)
        {
            return CreateDefaultResponse(packet);
        }

        private static string NextKeepLiveCSeq()
        {
            return ++keepLiveCSeq + " " + Helper_Sip.SipMethodName.Register;
        }

        private static SipResponse CreateDefaultResponse(SipMessage packet)
        {
            SipResponse response = new SipResponse(200, "OK");
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, packet.CallID.Value);
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, packet.CSeq.Value);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, packet.From.Value);
            if (packet.To != null)
            {
                SipHeadField hTo = new SipHeadField(Helper_Sip.SipHeadFieldName.To, packet.To.Value);
                response.HeadFields.Add(hTo);
            }
            if (packet.Supported != null)
            {
                SipHeadField hSupported = new SipHeadField(Helper_Sip.SipHeadFieldName.Supported, packet.Supported.Value);
                response.HeadFields.Add(hSupported);
            }
            response.HeadFields.Add(hFrom);
            response.HeadFields.Add(hCallID);
            response.HeadFields.Add(hCSeq);

            response.Body = Environment.NewLine;

            return response;
        }

        public static SipMessage HandleContactRequest(string userid)
        {
            //string msgContent = string.Format("<args><contacts><buddies><buddy uri=\"{0}\" result=\"1\" buddy-lists=\"\" expose-mobile-no=\"0\" expose-name=\"0\" /></buddies></contacts></args>", buddyUri.ToString());
            string msgContent = string.Format("<args><contacts><buddies><buddy user-id=\"{0}\" result=\"1\" buddy-lists=\"\" local-name=\"\" expose-mobile-no=\"1\" expose-name=\"1\" /></buddies></contacts></args>", userid);
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "HandleContactRequestV4");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage AddBuddy(SipUri buddyUri, string desc)
        {
            if (string.IsNullOrEmpty(desc))
                desc = Ower.NickName;
            string msgContent = string.Format("<args><contacts><buddies><buddy uri=\"{0}\" buddy-lists=\"\" desc=\"{1}\" expose-mobile-no=\"1\" expose-name=\"1\" addbuddy-phrase-id=\"0\" /></buddies></contacts></args>", buddyUri.ToString(), desc);
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "AddBuddyV4");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage DeleteBuddy(string userid)
        {
            string msgContent = string.Format("<args><contacts><buddies><buddy user-id=\"{0}\" /></buddies></contacts></args>", userid);
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "DeleteBuddyV4");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage SetPresence(PresenceStatus statu)
        {
            string msgContent = string.Format(string.Format("<args><presence><basic value=\"{0}\" /></presence></args>", (int)statu));
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "SetPresence");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage PGSetPresence()
        {
            string msgContent = string.Format("<args><groups /></args>");
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "PGSetPresence");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage GetGlobalPermission()
        {
            string msgContent = string.Format("<args><permissions objects=\"all\" /></args>");
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "GetGlobalPermission");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

        public static SipMessage GetContactPermission()
        {
            string msgContent = string.Format("<args><permissions all=\"1\" objects=\"all\" /></args>");
            SipRequest req = new SipRequest(Helper_Sip.SipMethodName.Service, DEFAULT_URI);
            SipHeadField hFrom = new SipHeadField(Helper_Sip.SipHeadFieldName.From, Ower.Uri.Sid.ToString());
            SipHeadField hCallID = new SipHeadField(Helper_Sip.SipHeadFieldName.CallID, Ower.Conncetion.NextCallID().ToString());
            SipHeadField hCSeq = new SipHeadField(Helper_Sip.SipHeadFieldName.CSeq, "1 " + Helper_Sip.SipMethodName.Service);
            SipHeadField hEvent = new SipHeadField(Helper_Sip.SipHeadFieldName.Event, "GetContactPermission");
            req.HeadFields.Add(hFrom);
            req.HeadFields.Add(hCallID);
            req.HeadFields.Add(hCSeq);
            req.HeadFields.Add(hEvent);
            req.Body = msgContent;
            return req;
        }

    }

    public class Protocol
    {
        public static string Version = "SIP-C/4.0";
    }

    public class Conversation
    {
        private BaseSipConnection connection;
        private SipUri from = null;
        private IList<Contact> participants = new List<Contact>();

        public event EventHandler<ConversationArgs> MsgRcv;

        public BaseSipConnection Connection
        {
            get { return connection; }
        }

        public SipUri From
        {
            get { return this.from; }
            set { this.from = value; }
        }

        //public string To { get; set; }
        private int callID = 0;
        public int CallID
        {
            get { return this.callID; }
            set { this.callID = value; }
        }

        private string cseq = string.Empty;
        public string CSeq
        {
            get { return this.cseq; }
            set { this.cseq = value; }
        }

        private SipEvent eventName = SipEvent.None;
        public SipEvent EventName
        {
            get { return this.eventName; }
            set { this.eventName = value; }
        }

        private SipMessage originPacket = null;
        public SipMessage OriginPacket
        {
            get { return this.originPacket; }
            set { this.originPacket = value; }
        }

        public IList<Contact> Participants
        {
            get { return this.participants; }
        }

        public Conversation()
        {
        }

        public Conversation(BaseSipConnection connection, SipMessage packet)
        {
            this.connection = connection;
            this.callID = int.Parse(packet.CallID.Value);
            this.cseq = packet.CSeq.Value;
            this.from = new SipUri(packet.From.Value);
            string eventStr = (packet.Event == null ? SipEvent.None.ToString() : packet.Event.Value);
            if (Enum.IsDefined(typeof(SipEvent), eventStr))
            {
                this.eventName = (SipEvent)Enum.Parse(typeof(SipEvent), eventStr, true);
            }
            this.originPacket = packet;
        }



        protected virtual void RcvRequest(SipRequest packet)
        {
            string sipMethod = packet.Method;
            EventHandler<ConversationArgs> msgHandler = this.MsgRcv;
            switch (sipMethod)
            {
                case Helper_Sip.SipMethodName.Invite:
                    this.ResponseInvite(packet);
                    break;
                case Helper_Sip.SipMethodName.Bye:
                    this.ResponseBye(packet);
                    break;
                case Helper_Sip.SipMethodName.Message:
                    this.ResponseReceiveMsg(packet);
                    if (msgHandler != null)
                    {
                        IMType imType = IMType.Internal;
                        //haozes edit 11/15
                        if (packet.ContentType == null || packet.ContentType.Value == "text/plain")
                        {
                            imType = IMType.SMS;//短信
                        }
                        else
                        {
                            imType = IMType.Text;//会话
                        }
                        msgHandler(this, new ConversationArgs(imType, packet));
                    }
                    break;
                default:
                    if (msgHandler != null)
                    {
                        if (this.eventName == SipEvent.AddBuddy)
                        {//也许有其他需要originPacket的地方
                            msgHandler(this, new ConversationArgs(IMType.Internal, packet, this.originPacket));
                        }
                        else
                        {
                            msgHandler(this, new ConversationArgs(IMType.Internal, packet));
                        }
                    }
                    break;
            }
        }

        protected virtual void RcvResponse(SipResponse packet)
        {
            EventHandler<ConversationArgs> msgHandler = this.MsgRcv;
            msgHandler(this, new ConversationArgs(IMType.Internal, packet));
        }

        public void RcvPacket(SipMessage packet)
        {
            SipRequest req = packet as SipRequest;
            if (req != null)
            {
                if (req[Helper_Sip.SipHeadFieldName.From] != null)
                {
                    this.from = new SipUri(req[Helper_Sip.SipHeadFieldName.From].Value);
                }
                this.RcvRequest(req);
            }
            else
            {
                this.RcvResponse(packet as SipResponse);
            }
        }

        //离线
        public void SendMsg(string content, bool isLeaveMsg)
        {
            SipMessage p = PacketFactory.LeaveMsgPacket(this.from, content);
            this.connection.Send(p);
        }

        //回复
        public void SendMsg(string msgContent)
        {
            SipMessage p = PacketFactory.ReplyMsgPacket(this, msgContent);
            this.connection.Send(p);
        }

        //短信
        public void SendSMS(string mobile, string content)
        {
        }

        //飞信短信
        public void SendSMS(string content)
        {
            SipMessage p = PacketFactory.SMSPacket(this.from, content);
            this.connection.Send(p);
        }

        /// <summary>
        /// 对方发送会话邀请 发送应答信号
        /// </summary>
        /// <param name="packet"></param>
        private void ResponseInvite(SipMessage packet)
        {
            SipMessage p = PacketFactory.RSPInvitePacket(packet);
            this.connection.Send(p);
        }

        /// <summary>
        /// 收到信息 发送收到消息成功的信号
        /// </summary>
        /// <param name="packet"></param>
        private void ResponseReceiveMsg(SipMessage packet)
        {
            SipMessage p = PacketFactory.RSPReceiveMsgPacket(packet);
            this.connection.Send(p);
        }

        /// <summary>
        /// 回复结束会话请求
        /// </summary>
        /// <param name="packet"></param>
        private void ResponseBye(SipMessage packet)
        {
            SipMessage p = PacketFactory.RSPBye(packet);
            this.connection.Send(p);
        }
    }
    
    public enum SipEvent
    {
        AddBuddy,
        AddMobileBuddy,
        Contact,
        Conversation,
        GetContactInfoV4,
        HandleContactRequestV4,
        Permission,
        PresenceV4,
        Registration,
        SyncUserInfoV4,//2010 协议
        None
    }

    /// <summary>
    /// 客户端在线状态
    /// </summary>
    public enum PresenceStatus
    {
        /// <summary>
        /// 隐身
        /// </summary>
        Invisible = 0,

        /// <summary>
        /// 离开
        /// </summary>
        Away = 100,

        /// <summary>
        /// 上线
        /// </summary>
        Active = 400,

        /// <summary>
        /// 离开
        /// </summary>
        Busy = 600,
        /// <summary>
        /// 接听电话
        /// </summary>
        InCall = 500,

        /// <summary>
        /// 马上回来
        /// </summary>
        BeRightBack = 300,

        /// <summary>
        /// 外出就餐
        /// </summary>
        AtLunch = 150
    }


    public class LoginMgr
    {
        private User user;
        private MessageParser msgParser;
        private ConversationMgr convMgr;

        private Conversation convRegSipcStep1;
        private Conversation convRegSipcStep2;

        //sipc第二步验证中的response
        private string sipcResponse = string.Empty;

        public event EventHandler<LoginEventArgs> LoginSucceed;
        public event EventHandler<LoginEventArgs> LoginFailed;

        public Func<string, byte[], string> VerifyCodeRequired { get; set; }

        public ConversationMgr ConversationManager
        {
            get { return this.convMgr; }
        }

        public LoginMgr(User user)
        {
            this.user = user;
        }

        public void Login()
        {
            EventHandler<LoginEventArgs> handlerFailed = this.LoginFailed;
            string password = this.user.Password;
            try
            {
                var con = this.user.MobileNo.ToString();
                this.GetSysConfig(con);
                this.SignInSSIServer(this.user.MobileNo.ToString(), password, string.Empty, string.Empty, string.Empty);
                this.SingInSipcServer();
            }
            catch (Exception ex)
            {
                if (handlerFailed != null)
                {
                    handlerFailed(this, new LoginEventArgs(ex.ToString()));
                }
            }
        }

        private void GetSysConfig(string mobile)
        {
            string postData = FetionTemplate.GetSystemConfigPostData(mobile);
            string configStr = HttpHelper.Post("http://nav.fetion.com.cn/nav/getsystemconfig.aspx", postData);
            if (!string.IsNullOrEmpty(configStr))
            {
                this.user.CreateSipSysConfig(configStr);
            }
        }

        private void SignInSSIServer(string mobile, string pwd, string pid, string pic, string algorithm)
        {
            string url;
            string digest =Helper_Security.EncryptV4(pwd);
            if (String.IsNullOrEmpty(pid))
            {
                url = string.Format("{0}?mobileno={1}&domains=fetion.com.cn%3bm161.com.cn%3bwww.ikuwa.cn%3bgames.fetion.com.cn%3bturn.fetion.com.cn%3bpos.fetion.com.cn&v4digest-type=1&v4digest={2}", this.user.SysConfig.SsiAppSignIn, mobile, digest);
            }
            else
            {
                url = string.Format("{0}?mobileno={1}&domains=fetion.com.cn%3bm161.com.cn%3bwww.ikuwa.cn%3bgames.fetion.com.cn%3bturn.fetion.com.cn%3bpos.fetion.com.cn&pid={3}&pic={4}&algorithm={5}&v4digest-type=1&v4digest={2}",
                    this.user.SysConfig.SsiAppSignIn, mobile, digest, pid, pic, algorithm);
            }
            try
            {
                string[] resultList = HttpHelper.Get(url, string.Empty);
              //  LogUtil.Log.Debug("step1:获取SSIC成功!");
                this.user.CreatePortInfo(resultList);
            }
            catch (WebException ex)
            {//不知道为啥.NET要在http状态非200的时候抛异常?!
                var rsp = (HttpWebResponse)ex.Response;
                string responseXml;
                string status;
                string desc = string.Empty;
                using (Stream dataStream = rsp.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
                    {
                        responseXml = reader.ReadToEnd();
                        XDocument doc = XDocument.Parse(responseXml);
                        status = doc.Element("results").Attribute("status-code").Value;
                        desc = doc.Element("results").Attribute("desc") == null ? string.Empty : doc.Element("results").Attribute("desc").Value;

                    }
                }
                if ((int)rsp.StatusCode == 200)
                {
                    return;
                }
                else if ((int)rsp.StatusCode == 421)
                {
                    XDocument doc = XDocument.Parse(responseXml);
                    string tip = doc.Element("results").Element("verification").Attribute("text").Value;
                    algorithm = doc.Element("results").Element("verification").Attribute("algorithm").Value;
                    byte[] picBuffer;
                    HttpHelper.GetPicCodeV4(algorithm, out picBuffer, out pid);
                    string picRsp = this.VerifyCodeRequired(tip, picBuffer);
                    this.SignInSSIServer(mobile, pwd, pid, picRsp, algorithm);
                }
                else
                {
                    this.LoginFailed(this, new LoginEventArgs(string.Format("状态码:{0},{1}", rsp.StatusCode, desc)));
                }
            }
        }

        private void SingInSipcServer()
        {
            this.SingInSipcStep1();
        }

        private void SingInSipcStep1()
        {
            string sendData = FetionTemplate.RegesterSIPCStep1(this.user.Uri.Sid.ToString());
            string[] addrStrArr = this.user.SysConfig.SipcProxy.Split(':');
            CreateConnection(addrStrArr[0], addrStrArr[1]);
            //cn值是随机的,可以自己创建.
            SipMessage step1data = PacketFactory.RegSipcStep1("d62aa14003cb0de2f252afa755df43cf");
            this.convRegSipcStep1 = this.convMgr.Create(step1data, true);
            this.convRegSipcStep1.MsgRcv += new EventHandler<ConversationArgs>(this.ConvRegSipcStep1_OnMsgRcv);
        }

        void ConvRegSipcStep1_OnMsgRcv(object sender, ConversationArgs e)
        {
            string nonce;
            string rsaKey;
            this.GetNonceAndRSAKey(e.RawPacket.WWWAuthenticate.Value, out nonce, out rsaKey);
            this.convRegSipcStep1.MsgRcv -= new EventHandler<ConversationArgs>(this.ConvRegSipcStep1_OnMsgRcv);
            this.convMgr.Remove(this.convRegSipcStep1.CallID);
            this.SingInSipcStep2(nonce, rsaKey);
        }

        private void CreateConnection(string ip, string port)
        {
            this.user.Conncetion.Connect(ip, port);
            PacketFactory.Ower = this.user;
            this.convMgr = new ConversationMgr(this.user.Conncetion);
            this.msgParser = new MessageParser(this.convMgr);
            this.user.Conncetion.MessageReceived += new EventHandler<ConversationArgs>(this.msgParser.ReceiveSipMessage);
            this.user.Conncetion.StartListen();
        }

        private void SingInSipcStep2(string nonce, string rsaKey)
        {
            if (string.IsNullOrEmpty(nonce))
                return;

            this.sipcResponse = HashPasswod.ComputeAuthResponse.ComputeNewResponse(this.user.UserId, this.user.Password, rsaKey, nonce);
            SipMessage step2data = PacketFactory.RegSipcStep2(this.sipcResponse);
            this.convRegSipcStep2 = this.convMgr.Create(step2data, true);
            this.convRegSipcStep2.MsgRcv += new EventHandler<ConversationArgs>(this.convRegSipcStep2_MsgRcv);
        }

        void convRegSipcStep2_MsgRcv(object sender, ConversationArgs e)
        {
            SipResponse rsp = e.RawPacket as SipResponse;
            if (rsp != null && rsp.StatusCode == 200)
            {
                //LogUtil.Log.Debug("step2:Sign in SIPC Server Successful!");
                this.user.CreatePersonalInfo(rsp.Body);
                this.user.ContactsManager.InitContactList(rsp.Body);
                EventHandler<LoginEventArgs> handlerSuccess = this.LoginSucceed;
                if (handlerSuccess != null)
                {
                    handlerSuccess(this, null);
                    this.convRegSipcStep2.MsgRcv -= new EventHandler<ConversationArgs>(this.convRegSipcStep2_MsgRcv);
                    this.convMgr.Remove(this.convRegSipcStep2.CallID);
                }
            }
            else if (rsp != null && rsp.StatusCode == 421)
            {//需要验证码
                string wwwAuth = rsp.WWWAuthenticate.Value.Trim();
                IDictionary<string, string> hash = GetKeyValueList(wwwAuth);

                string algorithm = hash["Verify algorithm"];
                string type = hash["type"];
                var doc = XDocument.Parse(rsp.Body);
                string reason = doc.Element("results").Element("reason").Attribute("text").Value;
                byte[] picBuffer;
                string chid;
                HttpHelper.GetPicCodeV4(algorithm, out picBuffer, out chid);
                string picRsp = this.VerifyCodeRequired(reason, picBuffer);

                SipMessage step2data = PacketFactory.RegSipcStep2(this.sipcResponse, algorithm, type, picRsp, chid);
                this.user.Conncetion.Send(step2data);
            }
            else if (rsp != null && rsp.StatusCode == 401)
            {
                this.LoginFailed(this, new LoginEventArgs("密码错误"));
            }
            else if (rsp != null && rsp.StatusCode == 420)
            {
                this.LoginFailed(this, new LoginEventArgs("输入验证码错误"));
            }
            else if (rsp != null && rsp.StatusCode == 424)
            {
                this.LoginFailed(this, new LoginEventArgs("登陆次数超过限制"));
            }
            else if (rsp != null && rsp.StatusCode == 431)
            {
                this.LoginFailed(this, new LoginEventArgs("用户正在更换飞信号，暂时无法登陆"));
            }
            else if (rsp != null && rsp.StatusCode == 432)
            {
                this.LoginFailed(this, new LoginEventArgs("当前飞信号已停止使用"));
            }
            else if (rsp != null && rsp.StatusCode == 435)
            {
                this.LoginFailed(this, new LoginEventArgs("您未绑定安全邮箱或手机号"));
            }
            else
            {
                this.LoginFailed(this, new LoginEventArgs("step2:Sign in SIPC Server failed!"));
            }
        }

        private void GetNonceAndRSAKey(string authHead, out string nonce, out string rsaKey)
        {
            IDictionary<string, string> hash = this.GetKeyValueList(authHead);
            nonce = hash["nonce"];
            rsaKey = hash["key"];
        }

        /// <summary>
        /// 分割这样的字符串为键值对 Verify algorithm="picc-WeakPassword",type="GeneralPic"
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private IDictionary<string, string> GetKeyValueList(string str)
        {
            Dictionary<string, string> hash = new Dictionary<string, string>();
            foreach (string s in str.Split(','))
            {
                int i = s.IndexOf('=');
                if (i > 0)
                {
                    hash.Add(s.Substring(0, i).Trim(), s.Substring(i + 1).Trim().Replace("\"", ""));
                }
            }
            return hash;
        }

    }

    public class LoginEventArgs : EventArgs
    {
        private string description = string.Empty;

        public LoginEventArgs()
        {
        }

        public LoginEventArgs(string description)
        {
            this.description = description;
        }

        public override string ToString()
        {
            return this.description;
        }
    }

    public class ConversationMgr
    {
        private object syncFlag = new object();
        private Dictionary<int, Conversation> convList = new Dictionary<int, Conversation>();
        private SipConnection connection = null;
        private IList<ChatConnection> chatConnections = new List<ChatConnection>();
        public event EventHandler<ConversationArgs> MsgReceived;
        /// 他处客户端登录 
        public event EventHandler Deregistered;
        /// 有人添加自己为好友
        public event EventHandler<ConversationArgs> AddBuddyRequest;

        public event EventHandler<ConversationArgs> PresenceNotify;

        public event EventHandler<ConversationArgs> SyncUserInfo;

        public ConversationMgr(SipConnection sipconection)
        {
            this.connection = sipconection;
        }

        public Conversation Create(BaseSipConnection conn, SipMessage packet, bool doSend)
        {
            int callID = int.Parse(packet.CallID.Value);
            Conversation conv = null;
            lock (this.syncFlag)
            {
                if (!this.convList.ContainsKey(callID))
                {
                    conv = new Conversation(conn, packet);
                    this.convList.Add(callID, conv);
                }
            }
            if (doSend)
            {
                conn.Send(packet);
            }
            return conv;
        }
        public Conversation Create(SipMessage packet)
        {
            return this.Create(this.connection, packet, false);
        }

        public Conversation Create(SipMessage packet, bool doSend)
        {
            return this.Create(this.connection, packet, true);
        }


        public ChatConnection CreateChatConnection(string remote, string port)
        {
            ChatConnection conn = new ChatConnection();
            try
            {
                conn.Connect(remote, port);
                this.chatConnections.Add(conn);
            }
            catch (SocketException ex)
            {
                //LogUtil.Log.Error(ex);
                conn = null;
            }

            return conn;
        }

        public void SendRawPacket(SipMessage packet)
        {
            this.connection.Send(packet);
        }

        public Conversation Find(int callID)
        {
            Conversation c = null;
            lock (this.convList)
            {
                if (this.convList.ContainsKey(callID))
                {
                    c = this.convList[callID];
                }
            }
            return c;
        }

        public Conversation Find(SipMessage packet)
        {
            int callID = int.Parse(packet.CallID.Value);
            return this.Find(callID);

        }

        public bool HasConversation(Conversation conv)
        {
            return this.convList.ContainsKey(conv.CallID);
        }

        public void Remove(int callID)
        {
            if (this.convList.ContainsKey(callID))
            {
                lock (this.syncFlag)
                {
                    this.convList.Remove(callID);
                }
            }
        }

        public void UserLeftConvsersation(int callid, IList<SipUri> uris)
        {
            Conversation conv = this.Find(callid);
            if (conv != null)
            {
                var conn = conv.Connection;
                var tmp = from p in conv.Participants
                          where uris.Contains(p.Uri) == true
                          select p;
                tmp.ToList().ForEach(p => conv.Participants.Remove(p));
                if (conv.Participants.Count < 2)
                {
                    conv.Connection.Close();
                    var con = (from c in this.chatConnections
                               where c.RemoteIP == conn.RemoteIP && c.RemotePort == conn.RemotePort
                               select c).FirstOrDefault();
                    if (con != null)
                    {
                        this.chatConnections.Remove(con);
                    }
                }
            }
        }

        public virtual void RaiseMsgRcv(object sender, ConversationArgs e)
        {
            if (this.MsgReceived != null)
            {
                this.MsgReceived(sender, e);
            }
        }

        public virtual void RaiseDeregistered(object sender, EventArgs e)
        {
            if (this.Deregistered != null)
            {
                this.Deregistered(sender, null);
            }
        }

        public virtual void RaiseAddBuddyApplication(object send, ConversationArgs e)
        {
            if (AddBuddyRequest != null)
                this.AddBuddyRequest(send, e);
        }

        public virtual void RaiseSyncUserInfo(object sender, ConversationArgs e)
        {
            if (SyncUserInfo != null)
                this.SyncUserInfo(this, e);
        }

        public virtual void RaisePresenceNotify(object send, ConversationArgs e)
        {
            if (PresenceNotify != null)
                this.PresenceNotify(this, e);
        }

        public void SendMsg(SipUri uri, string content)
        {
            SipMessage p = PacketFactory.LeaveMsgPacket(uri, content);
            this.connection.Send(p);
        }

        public void SendMsg(SipMessage rcvPacket, string msgContent)
        {
            SipMessage p = PacketFactory.ReplyMsgPacket(rcvPacket, msgContent);
            this.connection.Send(p);
        }

        public void SendSMS(string mobile, string content)
        {
            this.SendSMS(mobile, content, false);
        }

        /// <summary>
        /// Sends the SMS.
        /// </summary>
        /// <param name="mobile">The mobile.</param>
        /// <param name="content">The content.</param>
        /// <param name="isCatMsg">是否是长短信</param>
        public void SendSMS(string mobile, string content, bool isCatMsg)
        {
            this.SendSMS(new SipUri(mobile), content, isCatMsg);
        }

        public void SendSMS(SipUri uri, string content)
        {
            this.SendSMS(uri, content, false);
        }

        /// <summary>
        /// Sends the SMS.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="content">The content.</param>
        /// <param name="isCatMsg">是否是长短信</param>
        public void SendSMS(SipUri uri, string content, bool isCatMsg)
        {
            SipMessage p = PacketFactory.SMSPacket(uri, content, isCatMsg);
            this.connection.Send(p);
        }
    }

    public class FetionTemplate
    {
        public readonly string NavServerUrl = "http://nav.fetion.com.cn/nav/getsystemconfig.aspx";
        public static readonly string ClientVersion = "4.0.3390";

        public static string Tc()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("GET /nav/tc.aspx HTTP/1.1");
            sb.AppendLine("Host: nav.fetion.com.cn");
            sb.AppendLine("Connection: Close");
            sb.AppendLine("\r\n");
            return sb.ToString();
        }

        public static string GetSystemConfig(string mobile)
        {
            string xml = GetSystemConfigPostData(mobile);
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("POST /nav/getsystemconfig.aspx HTTP/1.1");
            sb.AppendLine("User-Agent: IIC2.0/PC " + ClientVersion);
            sb.AppendLine("Host: nav.fetion.com.cn");
            sb.AppendLine("Content-Length: " + xml.Length + "");
            sb.AppendLine("Connection: Close");
            sb.AppendLine(string.Empty);
            sb.AppendLine(xml);
            return sb.ToString();
        }

        public static string GetSystemConfigPostData(string mobile)
        {
            string xml = "<config><user mobile-no=\"" + mobile + "\" /><client type=\"PC\" version=\"" + FetionTemplate.ClientVersion + "\" platform=\"W5.1\" /><servers version=\"0\" /><service-no version=\"0\" /><parameters version=\"0\" /><hints version=\"0\" /><http-applications version=\"0\" /><client-config version=\"0\" /></config>";
            return xml;
        }

        public static string RegesterSIPCStep1(string sid)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("R fetion.com.cn " + Protocol.Version);
            sb.AppendLine("F: " + sid + "");
            sb.AppendLine("I: 1");
            sb.AppendLine("Q: 1 R");
            sb.AppendLine("CN: d62aa14003cb0de2f252afa755df43cf");
            sb.AppendLine("CL: type=\"pc\",version=\"4.0.3390\"");
            sb.AppendLine(string.Empty);
            return sb.ToString();
        }

        public static string RegesterSIPCStep2(string mobile, string userid, string sid, string response)
        {
            string arg = "<args><device accept-language=\"default\" machine-code=\"1F2E883F250398DEE59C33DD607A6B4C\" /><caps value=\"3FF\" /><events value=\"7F\" /><user-info mobile-no=\"" + mobile + "\" user-id=\"" + userid + "\"><personal version=\"0\" attributes=\"v4default;alv2-version;alv2-warn\" /><custom-config version=\"0\" /><contact-list version=\"0\" buddy-attributes=\"v4default\" /></user-info><credentials domains=\"fetion.com.cn;m161.com.cn;www.ikuwa.cn;games.fetion.com.cn;turn.fetion.com.cn\" /><presence><basic value=\"400\" desc=\"\" /><extendeds /></presence></args>";
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("R fetion.com.cn " + Protocol.Version);
            sb.AppendLine("F: " + sid + "");
            sb.AppendLine("I: 1");
            sb.AppendLine("Q: 2 R");
            sb.AppendLine(string.Format("A: Digest algorithm=\"SHA1-sess-v4\",response=\"{0}\"", response));
            sb.AppendLine("L: " + arg.Length + "");
            sb.AppendLine(string.Empty);
            sb.AppendLine(arg);

            return sb.ToString();
        }
        /******************************************************************************/
    }

    public class ChatConnection : BaseSipConnection
    {
        public override void Connect(string ip, string port)
        {
            this.remoteIp = ip;
            //don't catch exception here
            this.socket =Helper_TCP .CreateSocket(ip, port);
        }

        public override void Send(SipMessage packet)
        {
            try
            {
                Helper_TCP.AsyncSend(this.socket, packet, this.SendCallback);
            }
            catch (SocketException ex)
            {
               // LogUtil.Log.Debug("ChatConnection Send异常:" + ex.ToString());
                //not throw fata error,keep main thread not exit
               // ErrManager.RaiseError(new FxErrArgs(ErrLevel.Critical, ex));

            }
        }

        public override void StartKeepLive()
        {

        }
    }

    public class MessageParser
    {
        private ConversationMgr convMgr;

        public MessageParser(ConversationMgr convMgr)
        {
            this.convMgr = convMgr;
        }

        private IList<Contact> GetChatParticipants(string pkBody)
        {
            IList<Contact> list = new List<Contact>();
            Regex regexObj = new Regex(@"a=user:(sip:.+?;p=\d+)", RegexOptions.Singleline | RegexOptions.Multiline);
            Match matchResults = regexObj.Match(pkBody);
            while (matchResults.Success)
            {
                for (int i = 1; i < matchResults.Groups.Count; i++)
                {
                    Group groupObj = matchResults.Groups[i];
                    if (groupObj.Success)
                    {
                        SipUri sipUri = new SipUri(groupObj.Value);
                        Contact c = new Contact(sipUri);
                        list.Add(c);
                    }
                }
                matchResults = matchResults.NextMatch();
            }
            return list;
        }

        private void StartChat(SipMessage packet)
        {
            string a = packet.Authorization.Value.Trim();
            if (a.IndexOf("CS address", StringComparison.CurrentCultureIgnoreCase) < 0)
                return;

            var kvList = Helper_String.GetKeyValuePairs(a);
            string[] chatSvrs = Helper_String.GetKeyFromPairs("CS address", kvList).Split(';');
            string ticksAuth = Helper_String.GetKeyFromPairs("credential", kvList);

            IList<Contact> participants = GetChatParticipants(packet.Body);
            int callID = int.Parse(packet.CallID.Value);

            this.convMgr.Remove(callID);
            string remote = chatSvrs[0].Split(':')[0];
            string port = chatSvrs[0].Split(':')[1];
            ChatConnection conn = this.convMgr.CreateChatConnection(remote, port);

            if (conn != null)
            {
                conn.MessageReceived += new EventHandler<ConversationArgs>(ReceiveSipMessage);
                conn.StartListen();

                var sipdata = PacketFactory.RegToChatServer(callID.ToString(), ticksAuth);
                Conversation newConv = this.convMgr.Create(conn, sipdata, true);
                participants.ToList().ForEach(c => newConv.Participants.Add(c));
                if (newConv != null)
                {
                    newConv.MsgRcv += new EventHandler<ConversationArgs>(this.convMgr.RaiseMsgRcv);
                }
            }
        }

        public void ReceiveSipMessage(object sender, ConversationArgs e)
        {
            SipMessage packet = e.RawPacket;
            //DebugWriter.WriteRCVPacket(packet);
            SipRequest req = packet as SipRequest;

            Conversation conv = this.convMgr.Find(packet);
            if (conv != null)
            {
                conv.RcvPacket(packet);
            }

            if (req != null)
            {
                string sipMethod = req.Method;
                int callID = int.Parse(req.CallID.Value);
                switch (sipMethod)
                {
                    case Helper_Sip.SipMethodName.Invite:
                        this.StartChat(req);
                        break;
                    case Helper_Sip.SipMethodName.Message:
                        //haozes 11/25 手机客户端发来的ContentType为空
                        if (req.ContentType == null || string.Compare(req.ContentType.Value, "text/plain") == 0 || string.Compare(req.ContentType.Value, "text/html-fragment") == 0)
                        { //短信 
                            if (this.convMgr.Find(req) == null)
                            {
                                Conversation newSMSConv = this.convMgr.Create(req);
                                if (newSMSConv != null)
                                {
                                    newSMSConv.MsgRcv += new EventHandler<ConversationArgs>(this.convMgr.RaiseMsgRcv);
                                    newSMSConv.RcvPacket(req);
                                }
                            }
                        }
                        break;
                    case Helper_Sip. SipMethodName.Bye:
                        this.convMgr.Remove(callID);
                        break;
                    case Helper_Sip.SipMethodName.Benotify:
                        if (string.Equals(req.Event.Value, SipEvent.PresenceV4.ToString(), StringComparison.OrdinalIgnoreCase))
                        {
                            this.convMgr.RaisePresenceNotify(this, e);
                        }
                        else if (string.Equals(req.Event.Value, SipEvent.Registration.ToString(), StringComparison.OrdinalIgnoreCase))
                        { //registration
                            if (req.Body.IndexOf("deregistered") > 0)
                            {
                                this.convMgr.RaiseDeregistered(this, null);
                            }
                        }
                        else if (string.Equals(req.Event.Value, SipEvent.SyncUserInfoV4.ToString(), StringComparison.OrdinalIgnoreCase))
                        {
                            this.convMgr.RaiseSyncUserInfo(this, e);
                        }

                        else if (string.Equals(req.Event.Value, SipEvent.Contact.ToString(), StringComparison.OrdinalIgnoreCase))
                        { //contact 

                            string eventType = this.GetEventType(e.Text);
                            if (string.Equals(eventType, "AddBuddyApplication", StringComparison.OrdinalIgnoreCase))
                            {
                                convMgr.RaiseAddBuddyApplication(this, new ConversationArgs(IMType.AddBuddyRequest, req));
                            }
                        }
                        else if (string.Equals(req.Event.Value, SipEvent.Conversation.ToString(), StringComparison.CurrentCultureIgnoreCase))
                        {
                            string eventType = GetEventType(e.Text);
                            if (string.Equals(eventType, "UserLeft", StringComparison.CurrentCultureIgnoreCase))
                            {
                               // LogUtil.Log.Debug("UserLeft raised!");
                                this.convMgr.UserLeftConvsersation(callID, GetMember(e.Text));
                            }
                        }
                        break;
                    default:
                        break;
                } //switch end
            }
        }

        private string GetEventType(string pkContent)
        {
            string re = string.Empty;
            XmlDocument document = new XmlDocument();
            document.LoadXml(pkContent);
            XmlNode node = document.SelectSingleNode("events/event");
            if (node != null)
            {
                re =Helper_Data. XmlHelper.ReadXmlAttributeString(node, "type");
            }
            return re;
        }

        private IList<SipUri> GetMember(string pkContent)
        {
            IList<SipUri> list = new List<SipUri>();
            XDocument doc = XDocument.Parse(pkContent);
            var members = doc.Element("events")
                .Element("event")
                .Elements("member");

            members.ToList().ForEach(n => list.Add(new SipUri(n.Attribute("uri").Value)));
            return list;
        }
    }


    public static class HttpHelper
    {
        public static string Post(string url, string data)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            string responseHTML = string.Empty;

            byte[] replybyte = Encoding.UTF8.GetBytes(data);
            request = (HttpWebRequest)WebRequest.Create(url);
            request.UserAgent = "IIC2.0/PC " + FetionTemplate.ClientVersion;
            request.Method = "POST";
            //post 开始
            request.ContentLength = data.Length;
            using (Stream newStream = request.GetRequestStream())
            {
                newStream.Write(replybyte, 0, replybyte.Length);
            }

            //返回HTML
            response = (HttpWebResponse)request.GetResponse();
            using (Stream dataStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
                {
                    responseHTML = reader.ReadToEnd();
                }
            }
            return responseHTML;
        }

        /// <summary>
        /// 返回包含ssic和http response内容两个元素的数组
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="data">The data.</param>
        /// <returns>string[]</returns>
        public static string[] Get(string url, string data)
        {
            string[] list = new string[2];
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            string responseHTML = string.Empty;

            byte[] replybyte = Encoding.UTF8.GetBytes(data);
            ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
            request = (HttpWebRequest)WebRequest.Create(url);

            request.UserAgent = "IIC2.0/PC 4.0.0000";
            request.Method = "GET";

            //返回HTML
            response = (HttpWebResponse)request.GetResponse();
            string cookieStr = response.Headers["Set-Cookie"];
            string ssic = cookieStr.Split(';')[0].Trim();
            list[0] = ssic;
            //CookieCollection cookies = req.Cookies;
            using (Stream dataStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
                {
                    responseHTML = reader.ReadToEnd();
                }
            }
            list[1] = responseHTML;

            return list;
        }

        public static void GetPicCodeV4(string algorithm, out byte[] picBuffer, out  string chid)
        {
            string url = string.Format("http://nav.fetion.com.cn/nav/GetPicCodeV4.aspx?algorithm={0}", algorithm);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.UserAgent = "IIC2.0/PC 4.0.3390";
            request.Method = "GET";

            //返回HTML
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (Stream dataStream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
                {

                    XDocument doc = XDocument.Parse(reader.ReadToEnd());
                    string encryptedCode = doc.Element("results").Element("pic-certificate").Attribute("pic").Value;
                    picBuffer = Convert.FromBase64String(encryptedCode);
                    chid = doc.Element("results").Element("pic-certificate").Attribute("id").Value;
                }
            }
        }

        public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {   //   Always   accept   
            return true;
        }
    }

     


}


